summaryrefslogtreecommitdiffstats
path: root/src/gui/opengl/qopenglfunctions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/opengl/qopenglfunctions.cpp')
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp99
1 files changed, 72 insertions, 27 deletions
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index 99604ca8b2..d436fd45ec 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -3193,65 +3193,105 @@ static void QOPENGLF_APIENTRY qopenglfResolveVertexAttribPointer(GLuint indx, GL
#endif // !QT_OPENGL_ES_2
+// Functions part of the OpenGL ES 3.0+ standard need special handling. These,
+// just like the 2.0 functions, are not guaranteed to be resolvable via
+// eglGetProcAddress or similar. Calling them directly is, unlike the 2.0
+// functions, not feasible because one may build the binaries on a GLES3-capable
+// system and then deploy on a GLES2-only system that does not have these
+// symbols. Until ES3 gets universally available, they have to be dlsym'ed.
+
+Q_GLOBAL_STATIC(QOpenGLES3Helper, qgles3Helper)
+
+QOpenGLES3Helper::QOpenGLES3Helper()
+{
+#ifdef Q_OS_WIN
+#ifdef QT_DEBUG
+ m_gl.setFileName(QStringLiteral("libGLESv2"));
+#else
+ m_gl.setFileName(QStringLiteral("libGLESv2d"));
+#endif
+#else
+ m_gl.setFileName(QStringLiteral("GLESv2"));
+#endif
+ if (m_gl.load()) {
+ MapBufferRange = (GLvoid* (QOPENGLF_APIENTRYP)(GLenum, qopengl_GLintptr, qopengl_GLsizeiptr, GLbitfield)) m_gl.resolve("glMapBufferRange");
+ UnmapBuffer = (GLboolean (QOPENGLF_APIENTRYP)(GLenum)) m_gl.resolve("glUnmapBuffer");
+ BlitFramebuffer = (void (QOPENGLF_APIENTRYP)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum)) m_gl.resolve("glBlitFramebuffer");
+ RenderbufferStorageMultisample = (void (QOPENGLF_APIENTRYP)(GLenum, GLsizei, GLenum, GLsizei, GLsizei)) m_gl.resolve("glRenderbufferStorageMultisample");
+
+ GenVertexArrays = (void (QOPENGLF_APIENTRYP)(GLsizei, GLuint *)) m_gl.resolve("glGenVertexArrays");
+ DeleteVertexArrays = (void (QOPENGLF_APIENTRYP)(GLsizei, const GLuint *)) m_gl.resolve("glDeleteVertexArrays");
+ BindVertexArray = (void (QOPENGLF_APIENTRYP)(GLuint)) m_gl.resolve("glBindVertexArray");
+ IsVertexArray = (GLboolean (QOPENGLF_APIENTRYP)(GLuint)) m_gl.resolve("glIsVertexArray");
+
+ TexImage3D = (void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *)) m_gl.resolve("glTexImage3D");
+ TexSubImage3D = (void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *)) m_gl.resolve("glTexSubImage3D");
+ CompressedTexImage3D = (void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *)) m_gl.resolve("glCompressedTexImage3D");
+ CompressedTexSubImage3D = (void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *)) m_gl.resolve("glCompressedTexSubImage3D");
+
+ if (!MapBufferRange || !GenVertexArrays || !TexImage3D)
+ qFatal("OpenGL ES 3.0 entry points not found");
+ } else {
+ qFatal("Failed to load libGLESv2");
+ }
+}
+
+static inline bool isES3()
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ return ctx->isOpenGLES() && ctx->format().majorVersion() >= 3;
+}
+
static GLvoid *QOPENGLF_APIENTRY qopenglfResolveMapBuffer(GLenum target, GLenum access)
{
-#ifdef QT_OPENGL_ES_3
// It is possible that GL_OES_map_buffer is present, but then having to
// differentiate between glUnmapBufferOES and glUnmapBuffer causes extra
// headache. QOpenGLBuffer::map() will handle this automatically, while direct
// calls are better off with migrating to the standard glMapBufferRange.
- if (QOpenGLContext::currentContext()->format().majorVersion() >= 3) {
+ if (isES3()) {
qWarning("QOpenGLFunctions: glMapBuffer is not available in OpenGL ES 3.0 and up. Use glMapBufferRange instead.");
return 0;
- } else
-#endif
- RESOLVE_FUNC(GLvoid *, ResolveOES, MapBuffer)(target, access);
+ } else {
+ RESOLVE_FUNC(GLvoid *, ResolveOES, MapBuffer)(target, access);
+ }
}
static GLvoid *QOPENGLF_APIENTRY qopenglfResolveMapBufferRange(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr length, GLbitfield access)
{
-#ifdef QT_OPENGL_ES_3
- if (QOpenGLContext::currentContext()->format().majorVersion() >= 3)
- return ::glMapBufferRange(target, offset, length, access);
+ if (isES3())
+ return qgles3Helper()->MapBufferRange(target, offset, length, access);
else
-#endif
- RESOLVE_FUNC(GLvoid *, 0, MapBufferRange)(target, offset, length, access);
+ RESOLVE_FUNC(GLvoid *, 0, MapBufferRange)(target, offset, length, access);
}
static GLboolean QOPENGLF_APIENTRY qopenglfResolveUnmapBuffer(GLenum target)
{
-#ifdef QT_OPENGL_ES_3
- if (QOpenGLContext::currentContext()->format().majorVersion() >= 3)
- return ::glUnmapBuffer(target);
+ if (isES3())
+ return qgles3Helper()->UnmapBuffer(target);
else
-#endif
- RESOLVE_FUNC(GLboolean, ResolveOES, UnmapBuffer)(target);
+ RESOLVE_FUNC(GLboolean, ResolveOES, UnmapBuffer)(target);
}
static void QOPENGLF_APIENTRY qopenglfResolveBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter)
{
-#ifdef QT_OPENGL_ES_3
- if (QOpenGLContext::currentContext()->format().majorVersion() >= 3)
- ::glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ if (isES3())
+ qgles3Helper()->BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
else
-#endif
- RESOLVE_FUNC_VOID(ResolveEXT | ResolveANGLE | ResolveNV, BlitFramebuffer)
- (srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ RESOLVE_FUNC_VOID(ResolveEXT | ResolveANGLE | ResolveNV, BlitFramebuffer)
+ (srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
}
static void QOPENGLF_APIENTRY qopenglfResolveRenderbufferStorageMultisample(GLenum target, GLsizei samples,
GLenum internalFormat,
GLsizei width, GLsizei height)
{
-#ifdef QT_OPENGL_ES_3
- if (QOpenGLContext::currentContext()->format().majorVersion() >= 3)
- ::glRenderbufferStorageMultisample(target, samples, internalFormat, width, height);
+ if (isES3())
+ qgles3Helper()->RenderbufferStorageMultisample(target, samples, internalFormat, width, height);
else
-#endif
- RESOLVE_FUNC_VOID(ResolveEXT | ResolveANGLE | ResolveNV, RenderbufferStorageMultisample)
- (target, samples, internalFormat, width, height);
+ RESOLVE_FUNC_VOID(ResolveEXT | ResolveANGLE | ResolveNV, RenderbufferStorageMultisample)
+ (target, samples, internalFormat, width, height);
}
static void QOPENGLF_APIENTRY qopenglfResolveGetBufferSubData(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr size, GLvoid *data)
@@ -3506,4 +3546,9 @@ QOpenGLExtensionsPrivate::QOpenGLExtensionsPrivate(QOpenGLContext *ctx)
DiscardFramebuffer = qopenglfResolveDiscardFramebuffer;
}
+QOpenGLES3Helper *QOpenGLExtensions::gles3Helper()
+{
+ return qgles3Helper();
+}
+
QT_END_NAMESPACE