diff options
Diffstat (limited to 'src/gui/opengl/qopenglfunctions.cpp')
-rw-r--r-- | src/gui/opengl/qopenglfunctions.cpp | 141 |
1 files changed, 113 insertions, 28 deletions
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index bc4a714c6c..23861bd778 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -47,6 +47,10 @@ #include <QtGui/private/qguiapplication_p.h> #include <qpa/qplatformintegration.h> +#ifndef GL_FRAMEBUFFER_SRGB_CAPABLE_EXT +#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA +#endif + QT_BEGIN_NAMESPACE /*! @@ -126,6 +130,18 @@ QT_BEGIN_NAMESPACE glFuncs.glActiveTexture(GL_TEXTURE1); \endcode + An alternative approach is to query the context's associated + QOpenGLFunctions instance. This is somewhat faster than the previous + approach due to avoiding the creation of a new instance, but the difference + is fairly small since the internal data structures are shared, and function + resolving happens only once for a given context, regardless of the number of + QOpenGLFunctions instances initialized for it. + + \code + QOpenGLFunctions *glFuncs = QOpenGLContext::currentContext()->functions(); + glFuncs->glActiveTexture(GL_TEXTURE1); + \endcode + QOpenGLFunctions provides wrappers for all OpenGL ES 2.0 functions, including the common subset of OpenGL 1.x and ES 2.0. While such functions, for example glClear() or @@ -348,8 +364,6 @@ static int qt_gl_resolve_extensions() extensions |= QOpenGLExtensions::BGRATextureFormat; if (extensionMatcher.match("GL_ARB_texture_rectangle")) extensions |= QOpenGLExtensions::TextureRectangle; - if (extensionMatcher.match("GL_SGIS_generate_mipmap")) - extensions |= QOpenGLExtensions::GenerateMipmap; if (extensionMatcher.match("GL_ARB_texture_compression")) extensions |= QOpenGLExtensions::TextureCompression; if (extensionMatcher.match("GL_EXT_texture_compression_s3tc")) @@ -372,32 +386,52 @@ static int qt_gl_resolve_extensions() if (ctx->isOpenGLES()) { if (format.majorVersion() >= 2) extensions |= QOpenGLExtensions::GenerateMipmap; + + if (format.majorVersion() >= 3) { + extensions |= QOpenGLExtensions::PackedDepthStencil + | QOpenGLExtensions::Depth24 + | QOpenGLExtensions::ElementIndexUint + | QOpenGLExtensions::MapBufferRange + | QOpenGLExtensions::FramebufferBlit + | QOpenGLExtensions::FramebufferMultisample; + } else { + // Recognize features by extension name. + if (extensionMatcher.match("GL_OES_packed_depth_stencil")) + extensions |= QOpenGLExtensions::PackedDepthStencil; + if (extensionMatcher.match("GL_OES_depth24")) + extensions |= QOpenGLExtensions::Depth24; + if (extensionMatcher.match("GL_ANGLE_framebuffer_blit")) + extensions |= QOpenGLExtensions::FramebufferBlit; + if (extensionMatcher.match("GL_ANGLE_framebuffer_multisample")) + extensions |= QOpenGLExtensions::FramebufferMultisample; + if (extensionMatcher.match("GL_NV_framebuffer_blit")) + extensions |= QOpenGLExtensions::FramebufferBlit; + if (extensionMatcher.match("GL_NV_framebuffer_multisample")) + extensions |= QOpenGLExtensions::FramebufferMultisample; + } + if (extensionMatcher.match("GL_OES_mapbuffer")) extensions |= QOpenGLExtensions::MapBuffer; - if (extensionMatcher.match("GL_OES_packed_depth_stencil")) - extensions |= QOpenGLExtensions::PackedDepthStencil; if (extensionMatcher.match("GL_OES_element_index_uint")) extensions |= QOpenGLExtensions::ElementIndexUint; - if (extensionMatcher.match("GL_OES_depth24")) - extensions |= QOpenGLExtensions::Depth24; - // TODO: Consider matching GL_APPLE_texture_format_BGRA8888 as well, but it needs testing. + // We don't match GL_APPLE_texture_format_BGRA8888 here because it has different semantics. if (extensionMatcher.match("GL_IMG_texture_format_BGRA8888") || extensionMatcher.match("GL_EXT_texture_format_BGRA8888")) extensions |= QOpenGLExtensions::BGRATextureFormat; - if (extensionMatcher.match("GL_ANGLE_framebuffer_blit")) - extensions |= QOpenGLExtensions::FramebufferBlit; - if (extensionMatcher.match("GL_ANGLE_framebuffer_multisample")) - extensions |= QOpenGLExtensions::FramebufferMultisample; } else { extensions |= QOpenGLExtensions::ElementIndexUint | QOpenGLExtensions::MapBuffer; - // Recognize features by extension name. - if (format.majorVersion() >= 3 - || extensionMatcher.match("GL_ARB_framebuffer_object")) - { + if (format.version() >= qMakePair(1, 2)) + extensions |= QOpenGLExtensions::BGRATextureFormat; + + if (format.version() >= qMakePair(1, 4) || extensionMatcher.match("GL_SGIS_generate_mipmap")) + extensions |= QOpenGLExtensions::GenerateMipmap; + + if (format.majorVersion() >= 3 || extensionMatcher.match("GL_ARB_framebuffer_object")) { extensions |= QOpenGLExtensions::FramebufferMultisample | QOpenGLExtensions::FramebufferBlit | QOpenGLExtensions::PackedDepthStencil; } else { + // Recognize features by extension name. if (extensionMatcher.match("GL_EXT_framebuffer_multisample")) extensions |= QOpenGLExtensions::FramebufferMultisample; if (extensionMatcher.match("GL_EXT_framebuffer_blit")) @@ -405,19 +439,20 @@ static int qt_gl_resolve_extensions() if (extensionMatcher.match("GL_EXT_packed_depth_stencil")) extensions |= QOpenGLExtensions::PackedDepthStencil; } - } - if (format.renderableType() == QSurfaceFormat::OpenGL && format.version() >= qMakePair(3, 2)) - extensions |= QOpenGLExtensions::GeometryShaders; + if (format.version() >= qMakePair(3, 2) || extensionMatcher.match("GL_ARB_geometry_shader4")) + extensions |= QOpenGLExtensions::GeometryShaders; + + if (extensionMatcher.match("GL_ARB_map_buffer_range")) + extensions |= QOpenGLExtensions::MapBufferRange; -#ifndef QT_OPENGL_ES - if (extensionMatcher.match("GL_EXT_framebuffer_sRGB")) { - GLboolean srgbCapableFramebuffers = false; - ctx->functions()->glGetBooleanv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgbCapableFramebuffers); - if (srgbCapableFramebuffers) - extensions |= QOpenGLExtensions::SRGBFrameBuffer; + if (extensionMatcher.match("GL_EXT_framebuffer_sRGB")) { + GLboolean srgbCapableFramebuffers = false; + ctx->functions()->glGetBooleanv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgbCapableFramebuffers); + if (srgbCapableFramebuffers) + extensions |= QOpenGLExtensions::SRGBFrameBuffer; + } } -#endif return extensions; } @@ -2027,7 +2062,9 @@ namespace { enum ResolvePolicy { ResolveOES = 0x1, - ResolveEXT = 0x2 + ResolveEXT = 0x2, + ResolveANGLE = 0x4, + ResolveNV = 0x8 }; template <typename Base, typename FuncType, int Policy, typename ReturnType> @@ -2149,6 +2186,12 @@ private: if ((Policy & ResolveEXT) && !(funcs->*funcPointerName)) \ funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "EXT"); \ \ + if ((Policy & ResolveANGLE) && !(funcs->*funcPointerName)) \ + funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "ANGLE"); \ + \ + if ((Policy & ResolveNV) && !(funcs->*funcPointerName)) \ + funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "NV"); \ + \ if (!alternateFuncName.isEmpty() && !(funcs->*funcPointerName)) { \ funcs->*funcPointerName = (FuncType)context->getProcAddress(alternateFuncName); \ \ @@ -2160,6 +2203,12 @@ private: \ if ((Policy & ResolveEXT) && !(funcs->*funcPointerName)) \ funcs->*funcPointerName = (FuncType)context->getProcAddress(alternateFuncName + "EXT"); \ + \ + if ((Policy & ResolveANGLE) && !(funcs->*funcPointerName)) \ + funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "ANGLE"); \ + \ + if ((Policy & ResolveNV) && !(funcs->*funcPointerName)) \ + funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "NV"); \ } #define RESOLVER_COMMON_NON_VOID \ @@ -3144,11 +3193,36 @@ static void QOPENGLF_APIENTRY qopenglfResolveVertexAttribPointer(GLuint indx, GL 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) { + 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); } +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); + else +#endif + 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); + else +#endif RESOLVE_FUNC(GLboolean, ResolveOES, UnmapBuffer)(target); } @@ -3156,7 +3230,12 @@ static void QOPENGLF_APIENTRY qopenglfResolveBlitFramebuffer(GLint srcX0, GLint GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { - RESOLVE_FUNC_VOID_WITH_ALTERNATE(ResolveEXT, BlitFramebuffer, BlitFramebufferANGLE) +#ifdef QT_OPENGL_ES_3 + if (QOpenGLContext::currentContext()->format().majorVersion() >= 3) + ::glBlitFramebuffer(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); } @@ -3164,7 +3243,12 @@ static void QOPENGLF_APIENTRY qopenglfResolveRenderbufferStorageMultisample(GLen GLenum internalFormat, GLsizei width, GLsizei height) { - RESOLVE_FUNC_VOID_WITH_ALTERNATE(ResolveEXT, RenderbufferStorageMultisample, RenderbufferStorageMultisampleANGLE) +#ifdef QT_OPENGL_ES_3 + if (QOpenGLContext::currentContext()->format().majorVersion() >= 3) + ::glRenderbufferStorageMultisample(target, samples, internalFormat, width, height); + else +#endif + RESOLVE_FUNC_VOID(ResolveEXT | ResolveANGLE | ResolveNV, RenderbufferStorageMultisample) (target, samples, internalFormat, width, height); } @@ -3407,6 +3491,7 @@ QOpenGLExtensionsPrivate::QOpenGLExtensionsPrivate(QOpenGLContext *ctx) : QOpenGLFunctionsPrivate(ctx) { MapBuffer = qopenglfResolveMapBuffer; + MapBufferRange = qopenglfResolveMapBufferRange; UnmapBuffer = qopenglfResolveUnmapBuffer; BlitFramebuffer = qopenglfResolveBlitFramebuffer; RenderbufferStorageMultisample = qopenglfResolveRenderbufferStorageMultisample; |