diff options
Diffstat (limited to 'src/gui/opengl')
-rw-r--r-- | src/gui/opengl/qopenglextensions_p.h | 27 | ||||
-rw-r--r-- | src/gui/opengl/qopenglfunctions.cpp | 99 | ||||
-rw-r--r-- | src/gui/opengl/qopengltexturehelper.cpp | 33 | ||||
-rw-r--r-- | src/gui/opengl/qopenglvertexarrayobject.cpp | 16 |
4 files changed, 124 insertions, 51 deletions
diff --git a/src/gui/opengl/qopenglextensions_p.h b/src/gui/opengl/qopenglextensions_p.h index 0d0cfd26ba..6c3d923b1f 100644 --- a/src/gui/opengl/qopenglextensions_p.h +++ b/src/gui/opengl/qopenglextensions_p.h @@ -46,11 +46,36 @@ // #include "qopenglfunctions.h" +#include <QtCore/qlibrary.h> QT_BEGIN_NAMESPACE class QOpenGLExtensionsPrivate; +class QOpenGLES3Helper +{ +public: + QOpenGLES3Helper(); + + GLvoid* (QOPENGLF_APIENTRYP MapBufferRange)(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr length, GLbitfield access); + GLboolean (QOPENGLF_APIENTRYP UnmapBuffer)(GLenum target); + void (QOPENGLF_APIENTRYP BlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + void (QOPENGLF_APIENTRYP RenderbufferStorageMultisample)(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height); + + void (QOPENGLF_APIENTRYP GenVertexArrays)(GLsizei n, GLuint *arrays); + void (QOPENGLF_APIENTRYP DeleteVertexArrays)(GLsizei n, const GLuint *arrays); + void (QOPENGLF_APIENTRYP BindVertexArray)(GLuint array); + GLboolean (QOPENGLF_APIENTRYP IsVertexArray)(GLuint array); + + void (QOPENGLF_APIENTRYP TexImage3D)(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); + void (QOPENGLF_APIENTRYP TexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); + void (QOPENGLF_APIENTRYP CompressedTexImage3D)(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); + void (QOPENGLF_APIENTRYP CompressedTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); + +private: + QLibrary m_gl; +}; + class Q_GUI_EXPORT QOpenGLExtensions : public QOpenGLFunctions { Q_DECLARE_PRIVATE(QOpenGLExtensions) @@ -105,6 +130,8 @@ public: void glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments); + QOpenGLES3Helper *gles3Helper(); + private: static bool isInitialized(const QOpenGLFunctionsPrivate *d) { return d != 0; } }; 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 diff --git a/src/gui/opengl/qopengltexturehelper.cpp b/src/gui/opengl/qopengltexturehelper.cpp index 1eeab64911..d89e5d3236 100644 --- a/src/gui/opengl/qopengltexturehelper.cpp +++ b/src/gui/opengl/qopengltexturehelper.cpp @@ -34,6 +34,7 @@ #include "qopengltexturehelper_p.h" #include <QOpenGLContext> +#include <private/qopenglextensions_p.h> QT_BEGIN_NAMESPACE @@ -247,21 +248,23 @@ QOpenGLTextureHelper::QOpenGLTextureHelper(QOpenGLContext *context) CompressedTexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid*)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexImage3DOES"))); CompressedTexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexSubImage3DOES"))); } else { -#ifdef QT_OPENGL_ES_3 - // OpenGL ES 3.0+ has glTexImage3D. - TexImage3D = ::glTexImage3D; - TexSubImage3D = ::glTexSubImage3D; - CompressedTexImage3D = ::glCompressedTexImage3D; - CompressedTexSubImage3D = ::glCompressedTexSubImage3D; -#else - // OpenGL 1.2 - TexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLsizei , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glTexImage3D"))); - TexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLint , GLint , GLsizei , GLsizei , GLsizei , GLenum , GLenum , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glTexSubImage3D"))); - - // OpenGL 1.3 - CompressedTexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLenum , GLsizei , GLsizei , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexImage3D"))); - CompressedTexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLint , GLint , GLsizei , GLsizei , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexSubImage3D"))); -#endif + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + if (ctx->isOpenGLES() && ctx->format().majorVersion() >= 3) { + // OpenGL ES 3.0+ has glTexImage3D. + QOpenGLES3Helper *es3 = static_cast<QOpenGLExtensions *>(ctx->functions())->gles3Helper(); + TexImage3D = es3->TexImage3D; + TexSubImage3D = es3->TexSubImage3D; + CompressedTexImage3D = es3->CompressedTexImage3D; + CompressedTexSubImage3D = es3->CompressedTexSubImage3D; + } else { + // OpenGL 1.2 + TexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLsizei , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glTexImage3D"))); + TexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLint , GLint , GLsizei , GLsizei , GLsizei , GLenum , GLenum , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glTexSubImage3D"))); + + // OpenGL 1.3 + CompressedTexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLenum , GLsizei , GLsizei , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexImage3D"))); + CompressedTexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLint , GLint , GLsizei , GLsizei , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexSubImage3D"))); + } } #ifndef QT_OPENGL_ES_2 diff --git a/src/gui/opengl/qopenglvertexarrayobject.cpp b/src/gui/opengl/qopenglvertexarrayobject.cpp index 0fc140b3ef..42bb1a3a52 100644 --- a/src/gui/opengl/qopenglvertexarrayobject.cpp +++ b/src/gui/opengl/qopenglvertexarrayobject.cpp @@ -35,12 +35,12 @@ #include <QtCore/private/qobject_p.h> #include <QtGui/qopenglcontext.h> -#include <QtGui/qopenglfunctions.h> #include <QtGui/qoffscreensurface.h> #include <QtGui/qopenglfunctions_3_0.h> #include <QtGui/qopenglfunctions_3_2_core.h> +#include <private/qopenglextensions_p.h> #include <private/qopenglvertexarrayobject_p.h> QT_BEGIN_NAMESPACE @@ -56,16 +56,14 @@ void qtInitializeVertexArrayObjectHelper(QOpenGLVertexArrayObjectHelper *helper, bool tryARB = true; if (context->isOpenGLES()) { -#ifdef QT_OPENGL_ES_3 if (context->format().majorVersion() >= 3) { - helper->GenVertexArrays = ::glGenVertexArrays; - helper->DeleteVertexArrays = ::glDeleteVertexArrays; - helper->BindVertexArray = ::glBindVertexArray; - helper->IsVertexArray = ::glIsVertexArray; + QOpenGLES3Helper *es3 = static_cast<QOpenGLExtensions *>(context->functions())->gles3Helper(); + helper->GenVertexArrays = es3->GenVertexArrays; + helper->DeleteVertexArrays = es3->DeleteVertexArrays; + helper->BindVertexArray = es3->BindVertexArray; + helper->IsVertexArray = es3->IsVertexArray; tryARB = false; - } else -#endif - if (context->hasExtension(QByteArrayLiteral("GL_OES_vertex_array_object"))) { + } else if (context->hasExtension(QByteArrayLiteral("GL_OES_vertex_array_object"))) { helper->GenVertexArrays = reinterpret_cast<QOpenGLVertexArrayObjectHelper::qt_GenVertexArrays_t>(context->getProcAddress(QByteArrayLiteral("glGenVertexArraysOES"))); helper->DeleteVertexArrays = reinterpret_cast<QOpenGLVertexArrayObjectHelper::qt_DeleteVertexArrays_t>(context->getProcAddress(QByteArrayLiteral("glDeleteVertexArraysOES"))); helper->BindVertexArray = reinterpret_cast<QOpenGLVertexArrayObjectHelper::qt_BindVertexArray_t>(context->getProcAddress(QByteArrayLiteral("glBindVertexArrayOES"))); |