qmlgloverlay: make depth buffer optional

allow dropping depth/stencil buffer for
qmlgloverlay element. Shows considerable
drop in memory bandwidth consumption of
the element on windows platforms.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7677>
This commit is contained in:
Andreas Wittmann 2024-06-13 09:59:24 +02:00 committed by GStreamer Marge Bot
parent 5ef423fcaa
commit 41ad50fb48
9 changed files with 146 additions and 10 deletions

View file

@ -32,3 +32,4 @@
#include "buffers.h"
#include "query.h"
#include "buffer_storage.h"
#include "invalidate_subdata.h"

View file

@ -0,0 +1,66 @@
/*
* GStreamer
* Copyright (C) 2024 Andreas Wittmann <andreas.wittmann@zeiss.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
GST_GL_EXT_BEGIN (invalidate_subdata,
GST_GL_API_OPENGL3 |
GST_GL_API_GLES2,
4, 3,
3, 0,
"ARB:\0",
"invalidate_subdata\0")
GST_GL_EXT_FUNCTION (void, InvalidateFramebuffer,
(GLenum target,
GLsizei numAttachments,
const GLenum* attachments))
GST_GL_EXT_FUNCTION (void, InvalidateSubFramebuffer,
(GLenum target,
GLsizei numAttachments,
const GLenum* attachments,
GLint x,
GLint y,
GLsizei width,
GLsizei height))
GST_GL_EXT_END ()
GST_GL_EXT_BEGIN (invalidate_subdata_no_gles,
GST_GL_API_OPENGL3,
4, 3,
255, 255,
"ARB:\0",
"invalidate_subdata\0")
GST_GL_EXT_FUNCTION (void, InvalidateTexSubImage,
(GLuint texture,
GLint level,
GLint xoffset,
GLint yoffset,
GLint zoffset,
GLsizei width,
GLsizei height,
GLsizei depth))
GST_GL_EXT_FUNCTION (void, InvalidateTexImage,
(GLuint texture,
GLint level))
GST_GL_EXT_FUNCTION (void, InvalidateBufferSubData,
(GLuint buffer,
GLintptr offset,
GLsizeiptr length))
GST_GL_EXT_FUNCTION (void, InvalidateBufferData,
(GLuint buffer))
GST_GL_EXT_END ()

View file

@ -99,7 +99,7 @@ G_BEGIN_DECLS
struct _GstGLFuncs
{
#include <gst/gl/glprototypes/all_functions.h>
gpointer padding[GST_PADDING_LARGE*6-2];
gpointer padding[GST_PADDING_LARGE*6-8];
};
#undef GST_GL_EXT_BEGIN

View file

@ -103,6 +103,7 @@ gl_prototype_headers = files([
'glprototypes/gles.h',
'glprototypes/gstgl_compat.h',
'glprototypes/gstgl_gles2compat.h',
'glprototypes/invalidate_subdata.h',
'glprototypes/opengl.h',
'glprototypes/query.h',
'glprototypes/shaders.h',

View file

@ -12450,6 +12450,18 @@
"type": "GstGLContext",
"writable": false
},
"depth-buffer": {
"blurb": "Use depth and stencil buffer for the rendering of the scene. Might corrupt the rendering when set to FALSE! Only set to FALSE after carefully checking the targeted QML scene.",
"conditionally-available": false,
"construct": false,
"construct-only": false,
"controllable": false,
"default": "true",
"mutable": "ready",
"readable": true,
"type": "gboolean",
"writable": true
},
"qml-scene": {
"blurb": "The contents of the QML scene",
"conditionally-available": false,

View file

@ -145,6 +145,7 @@ enum
PROP_WIDGET,
PROP_QML_SCENE,
PROP_ROOT_ITEM,
PROP_DEPTH_AND_STENCIL_BUFFER,
};
enum
@ -204,6 +205,23 @@ gst_qt_overlay_class_init (GstQtOverlayClass * klass)
"The root QQuickItem from the qml-scene used to render",
(GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
/**
* GstQtOverlay:depth-buffer:
*
* Instructs QML to not use a depth or stencil buffer when rendering.
*
* WARNING: Disabling the depth and stencil buffer may cause QML to
* incorrectly render the provided scene.
*
* Since: 1.26
*/
g_object_class_install_property (gobject_class, PROP_DEPTH_AND_STENCIL_BUFFER,
g_param_spec_boolean ("depth-buffer", "Depth and Stencil Buffer",
"Use depth and stencil buffer for the rendering of the scene. "
"Might corrupt the rendering when set to FALSE! "
"Only set to FALSE after carefully checking the targeted QML scene.", TRUE,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_READY)));
/**
* GstQmlGLOverlay::qml-scene-initialized
* @element: the #GstQmlGLOverlay
@ -243,6 +261,7 @@ static void
gst_qt_overlay_init (GstQtOverlay * qt_overlay)
{
qt_overlay->widget = QSharedPointer<QtGLVideoItemInterface>();
qt_overlay->depth_buffer = TRUE;
qt_overlay->qml_scene = NULL;
}
@ -278,6 +297,9 @@ gst_qt_overlay_set_property (GObject * object, guint prop_id,
g_free (qt_overlay->qml_scene);
qt_overlay->qml_scene = g_value_dup_string (value);
break;
case PROP_DEPTH_AND_STENCIL_BUFFER:
qt_overlay->depth_buffer = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -316,6 +338,9 @@ gst_qt_overlay_get_property (GObject * object, guint prop_id,
}
GST_OBJECT_UNLOCK (qt_overlay);
break;
case PROP_DEPTH_AND_STENCIL_BUFFER:
g_value_set_boolean(value, qt_overlay->depth_buffer);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -341,7 +366,7 @@ gst_qt_overlay_gl_start (GstGLBaseFilter * bfilter)
GST_OBJECT_LOCK (bfilter);
qt_overlay->renderer = new GstQuickRenderer;
if (!qt_overlay->renderer->init (bfilter->context, &error)) {
if (!qt_overlay->renderer->init (bfilter->context, qt_overlay->depth_buffer, &error)) {
GST_ELEMENT_ERROR (GST_ELEMENT (bfilter), RESOURCE, NOT_FOUND,
("%s", error->message), (NULL));
delete qt_overlay->renderer;

View file

@ -51,6 +51,8 @@ struct _GstQtOverlay
/* <private> */
GstGLFilter parent;
gboolean depth_buffer;
gchar *qml_scene;
GstQuickRenderer *renderer;

View file

@ -21,6 +21,14 @@
#define GST_CAT_DEFAULT gst_qt_gl_renderer_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
// from GL_EXT_discard_framebuffer
#ifndef GL_DEPTH_EXT
#define GL_DEPTH_EXT 0x1801
#endif
#ifndef GL_STENCIL_EXT
#define GL_STENCIL_EXT 0x1802
#endif
static void
init_debug (void)
{
@ -217,6 +225,7 @@ GstQuickRenderer::GstQuickRenderer()
gl_allocator(NULL),
gl_params(NULL),
gl_mem(NULL),
m_useDepthBuffer(TRUE),
m_sharedRenderData(NULL)
{
init_debug ();
@ -292,7 +301,7 @@ bool CreateSurfaceWorker::event(QEvent * ev)
return QObject::event(ev);
}
bool GstQuickRenderer::init (GstGLContext * context, GError ** error)
bool GstQuickRenderer::init (GstGLContext * context, const gboolean use_depth_buffer, GError ** error)
{
g_return_val_if_fail (GST_IS_GL_CONTEXT (context), false);
g_return_val_if_fail (gst_gl_context_get_current () == context, false);
@ -306,6 +315,9 @@ bool GstQuickRenderer::init (GstGLContext * context, GError ** error)
return false;
}
m_useDepthBuffer = use_depth_buffer;
GST_DEBUG ("%s", m_useDepthBuffer ? "Use depth and stencil buffer" : "Discard depth and stencil buffer");
struct SharedRenderData *render_data = NULL, *old_render_data;
do {
if (render_data)
@ -551,7 +563,8 @@ void GstQuickRenderer::ensureFbo()
if (!m_fbo) {
m_fbo = new QOpenGLFramebufferObject(m_sharedRenderData->m_surface->size(),
QOpenGLFramebufferObject::CombinedDepthStencil);
m_useDepthBuffer ? QOpenGLFramebufferObject::CombinedDepthStencil :
QOpenGLFramebufferObject::NoAttachment);
m_quickWindow->setRenderTarget(m_fbo);
GST_DEBUG ("%p new framebuffer created with size %ix%i", this,
m_fbo->size().width(), m_fbo->size().height());
@ -584,6 +597,23 @@ GstQuickRenderer::renderGstGL ()
/* Meanwhile on this thread continue with the actual rendering. */
m_renderControl->render();
{
GLint currentFbo = -1;
gl->GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &currentFbo);
if ((GLuint)currentFbo == m_fbo->handle()) {
if (gl->InvalidateFramebuffer) {
const GLenum attachments[] = { GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT };
gl->InvalidateFramebuffer(GL_FRAMEBUFFER, sizeof(attachments) / sizeof(*attachments), attachments);
} else if (gl->DiscardFramebuffer) {
const GLenum attachments[] = { GL_DEPTH_EXT, GL_STENCIL_EXT };
gl->DiscardFramebuffer(GL_FRAMEBUFFER, sizeof(attachments) / sizeof(*attachments), attachments);
} else {
GST_DEBUG ("Context lacks both - GL_ARB_invalidate_subdata and GL_EXT_discard_framebuffer, cannot discard");
}
}
}
GST_DEBUG ("wrapping Qfbo %p with texture %u", m_fbo, m_fbo->texture());
struct FBOUserData *data = g_new0 (struct FBOUserData, 1);
data->context = (GstGLContext *) gst_object_ref (gl_context);

View file

@ -44,11 +44,10 @@ public:
GstQuickRenderer();
~GstQuickRenderer();
/* initialize the GStreamer/Qt integration. On failure returns false
* and fills @error.
* Must be called with @context not wrapped and current in the current
* thread */
bool init (GstGLContext * context, GError ** error);
/* initialize the GStreamer/Qt integration and determine wether to attach depth/stencil buffer to fbo. On failure
* returns false and fills @error. Must be called with @context not wrapped and current in the current thread
*/
bool init (GstGLContext * context, const gboolean use_depth_buffer, GError ** error);
/* set the qml scene. returns false and fills @error on failure */
bool setQmlScene (const gchar * scene, GError ** error);
@ -101,7 +100,7 @@ private:
GstGLAllocationParams *gl_params;
GstVideoInfo v_info;
GstGLMemory *gl_mem;
gboolean m_useDepthBuffer;
QString m_errorString;
struct SharedRenderData *m_sharedRenderData;
};