From 8cc8bbb466fb871585bfa1d5c56fc8bc6d6c8a96 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Fri, 21 Jul 2023 13:48:35 +0200 Subject: [PATCH] QOpenGLWidget: use (and prefer) InvalidateFramebuffer Desktop GL does not have the GL_EXT_discard_framebuffer extension at all. Instead, it may have GL_ARB_invalidate_subdata. Furthermore, GLES >= 3.0 and GL >= 4.3 both support FBO invalidation through glInvalidateFramebuffer. Extend the semantics of OpenGLExtension::DiscardFramebuffer to mean that *any* possibility above is supported, and wrap it in a helper function that calls whatever support is present. (This is all private API anyhow.) Technically speaking glInvalidateFramebuffer supports a superset of what glDiscardFramebufferEXT supports, but we never use such superset, and the two APIs are otherwise identical. Then, make QOpenGLWidget call that wrapper. Change-Id: I64e042daf51493d3834c3ba1b53ae6e224bbc4ed Reviewed-by: Laszlo Agocs --- src/gui/opengl/qopenglextensions_p.h | 10 +--------- src/gui/opengl/qopenglfunctions.cpp | 22 +++++++++++++++++++++- src/openglwidgets/qopenglwidget.cpp | 7 +++---- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/gui/opengl/qopenglextensions_p.h b/src/gui/opengl/qopenglextensions_p.h index 58231545c6..a6c4a68c6c 100644 --- a/src/gui/opengl/qopenglextensions_p.h +++ b/src/gui/opengl/qopenglextensions_p.h @@ -70,9 +70,9 @@ public: GLvoid *glMapBuffer(GLenum target, GLenum access); void glGetBufferSubData(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr size, GLvoid *data); - void glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments); void flushShared(); + void discardFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments); QOpenGLExtensionsPrivate *d() const; @@ -117,14 +117,6 @@ inline void QOpenGLExtensions::glGetBufferSubData(GLenum target, qopengl_GLintpt Q_OPENGL_FUNCTIONS_DEBUG } - -inline void QOpenGLExtensions::glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments) -{ - Q_D(QOpenGLExtensions); - Q_ASSERT(QOpenGLExtensions::isInitialized(d)); - d->DiscardFramebuffer(target,numAttachments, attachments); - Q_OPENGL_FUNCTIONS_DEBUG -} QT_END_NAMESPACE #endif // QOPENGL_EXTENSIONS_P_H diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index 0b760eb2dd..c9352fbc31 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -365,6 +365,7 @@ static int qt_gl_resolve_extensions() | QOpenGLExtensions::FramebufferBlit | QOpenGLExtensions::FramebufferMultisample | QOpenGLExtensions::Sized8Formats + | QOpenGLExtensions::DiscardFramebuffer | QOpenGLExtensions::StandardDerivatives | QOpenGLExtensions::ETC2TextureCompression | QOpenGLExtensions::HalfFloatVertex; @@ -450,6 +451,9 @@ static int qt_gl_resolve_extensions() if (format.version() >= qMakePair(3, 3)) extensions |= QOpenGLExtensions::TextureSwizzle; + if (format.version() >= qMakePair(4, 3) || extensionMatcher.match("GL_ARB_invalidate_subdata")) + extensions |= QOpenGLExtensions::DiscardFramebuffer; + if (extensionMatcher.match("GL_ARB_map_buffer_range")) extensions |= QOpenGLExtensions::MapBufferRange; @@ -5051,7 +5055,23 @@ QOpenGLExtensionsPrivate::QOpenGLExtensionsPrivate(QOpenGLContext *ctx) MapBuffer = RESOLVE(MapBuffer); GetBufferSubData = RESOLVE(GetBufferSubData); DiscardFramebuffer = RESOLVE(DiscardFramebuffer); - } +} + +void QOpenGLExtensions::discardFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments) +{ + Q_D(QOpenGLExtensions); + Q_ASSERT(QOpenGLExtensions::isInitialized(d)); + Q_ASSERT(d->f.InvalidateFramebuffer || d->DiscardFramebuffer); + + // On GLES >= 3 we prefer glInvalidateFramebuffer, even if the + // discard extension is present + if (d->f.InvalidateFramebuffer) + d->f.InvalidateFramebuffer(target, numAttachments, attachments); + else + d->DiscardFramebuffer(target, numAttachments, attachments); + + Q_OPENGL_FUNCTIONS_DEBUG +} void QOpenGLExtensions::flushShared() { diff --git a/src/openglwidgets/qopenglwidget.cpp b/src/openglwidgets/qopenglwidget.cpp index 5fae60ee17..1733706437 100644 --- a/src/openglwidgets/qopenglwidget.cpp +++ b/src/openglwidgets/qopenglwidget.cpp @@ -504,9 +504,8 @@ QT_BEGIN_NAMESPACE benefits on certain hardware architectures common in the mobile and embedded space when a framebuffer object is used as the rendering target. The framebuffer object is invalidated between frames with - glDiscardFramebufferEXT if supported or a glClear. Please see the - documentation of EXT_discard_framebuffer for more information: - https://www.khronos.org/registry/gles/extensions/EXT/EXT_discard_framebuffer.txt + glInvalidateFramebuffer (if supported), or, as fallbacks, + glDiscardFramebufferEXT (if supported) or a call to glClear. \value PartialUpdate The framebuffer objects color buffer and ancillary buffers are not invalidated between frames. @@ -1000,7 +999,7 @@ void QOpenGLWidgetPrivate::invalidateFbo() gl_color_attachment0, gl_depth_attachment, gl_stencil_attachment }; #endif - f->glDiscardFramebufferEXT(GL_FRAMEBUFFER, sizeof attachments / sizeof *attachments, attachments); + f->discardFramebuffer(GL_FRAMEBUFFER, GLsizei(std::size(attachments)), attachments); } else { f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); }