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 <laszlo.agocs@qt.io>
bb10
Giuseppe D'Angelo 2023-07-21 13:48:35 +02:00
parent abe7c77d6d
commit 8cc8bbb466
3 changed files with 25 additions and 14 deletions

View File

@ -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

View File

@ -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()
{

View File

@ -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);
}