mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-22 09:41:07 +00:00
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:
parent
5ef423fcaa
commit
41ad50fb48
9 changed files with 146 additions and 10 deletions
|
@ -32,3 +32,4 @@
|
||||||
#include "buffers.h"
|
#include "buffers.h"
|
||||||
#include "query.h"
|
#include "query.h"
|
||||||
#include "buffer_storage.h"
|
#include "buffer_storage.h"
|
||||||
|
#include "invalidate_subdata.h"
|
|
@ -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 ()
|
|
@ -99,7 +99,7 @@ G_BEGIN_DECLS
|
||||||
struct _GstGLFuncs
|
struct _GstGLFuncs
|
||||||
{
|
{
|
||||||
#include <gst/gl/glprototypes/all_functions.h>
|
#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
|
#undef GST_GL_EXT_BEGIN
|
||||||
|
|
|
@ -103,6 +103,7 @@ gl_prototype_headers = files([
|
||||||
'glprototypes/gles.h',
|
'glprototypes/gles.h',
|
||||||
'glprototypes/gstgl_compat.h',
|
'glprototypes/gstgl_compat.h',
|
||||||
'glprototypes/gstgl_gles2compat.h',
|
'glprototypes/gstgl_gles2compat.h',
|
||||||
|
'glprototypes/invalidate_subdata.h',
|
||||||
'glprototypes/opengl.h',
|
'glprototypes/opengl.h',
|
||||||
'glprototypes/query.h',
|
'glprototypes/query.h',
|
||||||
'glprototypes/shaders.h',
|
'glprototypes/shaders.h',
|
||||||
|
|
|
@ -12450,6 +12450,18 @@
|
||||||
"type": "GstGLContext",
|
"type": "GstGLContext",
|
||||||
"writable": false
|
"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": {
|
"qml-scene": {
|
||||||
"blurb": "The contents of the QML scene",
|
"blurb": "The contents of the QML scene",
|
||||||
"conditionally-available": false,
|
"conditionally-available": false,
|
||||||
|
|
|
@ -145,6 +145,7 @@ enum
|
||||||
PROP_WIDGET,
|
PROP_WIDGET,
|
||||||
PROP_QML_SCENE,
|
PROP_QML_SCENE,
|
||||||
PROP_ROOT_ITEM,
|
PROP_ROOT_ITEM,
|
||||||
|
PROP_DEPTH_AND_STENCIL_BUFFER,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -204,6 +205,23 @@ gst_qt_overlay_class_init (GstQtOverlayClass * klass)
|
||||||
"The root QQuickItem from the qml-scene used to render",
|
"The root QQuickItem from the qml-scene used to render",
|
||||||
(GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
|
(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
|
* GstQmlGLOverlay::qml-scene-initialized
|
||||||
* @element: the #GstQmlGLOverlay
|
* @element: the #GstQmlGLOverlay
|
||||||
|
@ -243,6 +261,7 @@ static void
|
||||||
gst_qt_overlay_init (GstQtOverlay * qt_overlay)
|
gst_qt_overlay_init (GstQtOverlay * qt_overlay)
|
||||||
{
|
{
|
||||||
qt_overlay->widget = QSharedPointer<QtGLVideoItemInterface>();
|
qt_overlay->widget = QSharedPointer<QtGLVideoItemInterface>();
|
||||||
|
qt_overlay->depth_buffer = TRUE;
|
||||||
qt_overlay->qml_scene = NULL;
|
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);
|
g_free (qt_overlay->qml_scene);
|
||||||
qt_overlay->qml_scene = g_value_dup_string (value);
|
qt_overlay->qml_scene = g_value_dup_string (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_DEPTH_AND_STENCIL_BUFFER:
|
||||||
|
qt_overlay->depth_buffer = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -316,6 +338,9 @@ gst_qt_overlay_get_property (GObject * object, guint prop_id,
|
||||||
}
|
}
|
||||||
GST_OBJECT_UNLOCK (qt_overlay);
|
GST_OBJECT_UNLOCK (qt_overlay);
|
||||||
break;
|
break;
|
||||||
|
case PROP_DEPTH_AND_STENCIL_BUFFER:
|
||||||
|
g_value_set_boolean(value, qt_overlay->depth_buffer);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -341,7 +366,7 @@ gst_qt_overlay_gl_start (GstGLBaseFilter * bfilter)
|
||||||
|
|
||||||
GST_OBJECT_LOCK (bfilter);
|
GST_OBJECT_LOCK (bfilter);
|
||||||
qt_overlay->renderer = new GstQuickRenderer;
|
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,
|
GST_ELEMENT_ERROR (GST_ELEMENT (bfilter), RESOURCE, NOT_FOUND,
|
||||||
("%s", error->message), (NULL));
|
("%s", error->message), (NULL));
|
||||||
delete qt_overlay->renderer;
|
delete qt_overlay->renderer;
|
||||||
|
|
|
@ -51,6 +51,8 @@ struct _GstQtOverlay
|
||||||
/* <private> */
|
/* <private> */
|
||||||
GstGLFilter parent;
|
GstGLFilter parent;
|
||||||
|
|
||||||
|
gboolean depth_buffer;
|
||||||
|
|
||||||
gchar *qml_scene;
|
gchar *qml_scene;
|
||||||
|
|
||||||
GstQuickRenderer *renderer;
|
GstQuickRenderer *renderer;
|
||||||
|
|
|
@ -21,6 +21,14 @@
|
||||||
#define GST_CAT_DEFAULT gst_qt_gl_renderer_debug
|
#define GST_CAT_DEFAULT gst_qt_gl_renderer_debug
|
||||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
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
|
static void
|
||||||
init_debug (void)
|
init_debug (void)
|
||||||
{
|
{
|
||||||
|
@ -217,6 +225,7 @@ GstQuickRenderer::GstQuickRenderer()
|
||||||
gl_allocator(NULL),
|
gl_allocator(NULL),
|
||||||
gl_params(NULL),
|
gl_params(NULL),
|
||||||
gl_mem(NULL),
|
gl_mem(NULL),
|
||||||
|
m_useDepthBuffer(TRUE),
|
||||||
m_sharedRenderData(NULL)
|
m_sharedRenderData(NULL)
|
||||||
{
|
{
|
||||||
init_debug ();
|
init_debug ();
|
||||||
|
@ -292,7 +301,7 @@ bool CreateSurfaceWorker::event(QEvent * ev)
|
||||||
return QObject::event(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_IS_GL_CONTEXT (context), false);
|
||||||
g_return_val_if_fail (gst_gl_context_get_current () == 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;
|
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;
|
struct SharedRenderData *render_data = NULL, *old_render_data;
|
||||||
do {
|
do {
|
||||||
if (render_data)
|
if (render_data)
|
||||||
|
@ -551,7 +563,8 @@ void GstQuickRenderer::ensureFbo()
|
||||||
|
|
||||||
if (!m_fbo) {
|
if (!m_fbo) {
|
||||||
m_fbo = new QOpenGLFramebufferObject(m_sharedRenderData->m_surface->size(),
|
m_fbo = new QOpenGLFramebufferObject(m_sharedRenderData->m_surface->size(),
|
||||||
QOpenGLFramebufferObject::CombinedDepthStencil);
|
m_useDepthBuffer ? QOpenGLFramebufferObject::CombinedDepthStencil :
|
||||||
|
QOpenGLFramebufferObject::NoAttachment);
|
||||||
m_quickWindow->setRenderTarget(m_fbo);
|
m_quickWindow->setRenderTarget(m_fbo);
|
||||||
GST_DEBUG ("%p new framebuffer created with size %ix%i", this,
|
GST_DEBUG ("%p new framebuffer created with size %ix%i", this,
|
||||||
m_fbo->size().width(), m_fbo->size().height());
|
m_fbo->size().width(), m_fbo->size().height());
|
||||||
|
@ -584,6 +597,23 @@ GstQuickRenderer::renderGstGL ()
|
||||||
/* Meanwhile on this thread continue with the actual rendering. */
|
/* Meanwhile on this thread continue with the actual rendering. */
|
||||||
m_renderControl->render();
|
m_renderControl->render();
|
||||||
|
|
||||||
|
{
|
||||||
|
GLint currentFbo = -1;
|
||||||
|
gl->GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤tFbo);
|
||||||
|
|
||||||
|
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());
|
GST_DEBUG ("wrapping Qfbo %p with texture %u", m_fbo, m_fbo->texture());
|
||||||
struct FBOUserData *data = g_new0 (struct FBOUserData, 1);
|
struct FBOUserData *data = g_new0 (struct FBOUserData, 1);
|
||||||
data->context = (GstGLContext *) gst_object_ref (gl_context);
|
data->context = (GstGLContext *) gst_object_ref (gl_context);
|
||||||
|
|
|
@ -44,11 +44,10 @@ public:
|
||||||
GstQuickRenderer();
|
GstQuickRenderer();
|
||||||
~GstQuickRenderer();
|
~GstQuickRenderer();
|
||||||
|
|
||||||
/* initialize the GStreamer/Qt integration. On failure returns false
|
/* initialize the GStreamer/Qt integration and determine wether to attach depth/stencil buffer to fbo. On failure
|
||||||
* and fills @error.
|
* returns false and fills @error. Must be called with @context not wrapped and current in the current thread
|
||||||
* Must be called with @context not wrapped and current in the current
|
*/
|
||||||
* thread */
|
bool init (GstGLContext * context, const gboolean use_depth_buffer, GError ** error);
|
||||||
bool init (GstGLContext * context, GError ** error);
|
|
||||||
|
|
||||||
/* set the qml scene. returns false and fills @error on failure */
|
/* set the qml scene. returns false and fills @error on failure */
|
||||||
bool setQmlScene (const gchar * scene, GError ** error);
|
bool setQmlScene (const gchar * scene, GError ** error);
|
||||||
|
@ -101,7 +100,7 @@ private:
|
||||||
GstGLAllocationParams *gl_params;
|
GstGLAllocationParams *gl_params;
|
||||||
GstVideoInfo v_info;
|
GstVideoInfo v_info;
|
||||||
GstGLMemory *gl_mem;
|
GstGLMemory *gl_mem;
|
||||||
|
gboolean m_useDepthBuffer;
|
||||||
QString m_errorString;
|
QString m_errorString;
|
||||||
struct SharedRenderData *m_sharedRenderData;
|
struct SharedRenderData *m_sharedRenderData;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue