finally working for RHI and the Qt5 OpenGL legacy backends

This commit is contained in:
Uwe Rathmann 2023-12-28 17:02:30 +01:00
parent ff10fc6fc1
commit 1bc7cc3097
2 changed files with 91 additions and 42 deletions

View File

@ -29,6 +29,26 @@ QSK_QT_PRIVATE_END
#include <qopenglframebufferobject.h> #include <qopenglframebufferobject.h>
#endif #endif
static int qskRenderOrderCompare( const QSGNode* rootNode,
const QSGNode* node1, const QSGNode* node2 )
{
if ( rootNode == node1 )
return 1;
if ( rootNode == node2 )
return -1;
for ( auto node = rootNode->firstChild();
node != nullptr; node = node->nextSibling() )
{
const auto ret = qskRenderOrderCompare( node, node1, node2 );
if ( ret )
return ret;
}
return 0;
}
namespace namespace
{ {
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) #if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
@ -51,7 +71,20 @@ namespace
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) #if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
inline int textureId() const { return m_fbo ? m_fbo->texture() : 0; } inline int textureId() const { return m_fbo ? m_fbo->texture() : 0; }
inline void renderScene() { Inherited::renderScene( textureId() ); }
inline void renderScene()
{
class Bindable : public QSGBindable
{
public:
Bindable( QOpenGLFramebufferObject* fbo ) : m_fbo( fbo ) {}
void bind() const override { m_fbo->bind(); }
private:
QOpenGLFramebufferObject* m_fbo;
};
Inherited::renderScene( Bindable( m_fbo ) );
}
#endif #endif
inline QRhiTexture* rhiTexture() const { return m_rhiTexture; } inline QRhiTexture* rhiTexture() const { return m_rhiTexture; }
@ -62,6 +95,7 @@ namespace
void setProjection( const QRectF& ); void setProjection( const QRectF& );
void setTextureSize( const QSize& ); void setTextureSize( const QSize& );
QSize textureSize() const;
protected: protected:
void nodeChanged( QSGNode*, QSGNode::DirtyState ) override; void nodeChanged( QSGNode*, QSGNode::DirtyState ) override;
@ -70,6 +104,7 @@ namespace
private: private:
void createTarget( const QSize& ); void createTarget( const QSize& );
void clearTarget(); void clearTarget();
void markDirty();
QSGTransformNode* m_finalNode = nullptr; QSGTransformNode* m_finalNode = nullptr;
QskSceneTexture* m_texture = nullptr; QskSceneTexture* m_texture = nullptr;
@ -100,6 +135,9 @@ namespace
, m_texture( texture ) , m_texture( texture )
{ {
setClearColor( Qt::transparent ); setClearColor( Qt::transparent );
connect( this, &QSGRenderer::sceneGraphChanged,
this, &Renderer::markDirty );
} }
Renderer::~Renderer() Renderer::~Renderer()
@ -112,6 +150,7 @@ namespace
if ( node != m_finalNode ) if ( node != m_finalNode )
{ {
m_finalNode = node; m_finalNode = node;
markDirty();
} }
} }
@ -169,6 +208,11 @@ namespace
setViewportRect( r ); setViewportRect( r );
} }
QSize Renderer::textureSize() const
{
return m_fbo ? m_fbo->size() : QSize();
}
void Renderer::render() void Renderer::render()
{ {
m_dirty = false; m_dirty = false;
@ -186,16 +230,25 @@ namespace
void Renderer::nodeChanged( QSGNode* node, QSGNode::DirtyState state ) void Renderer::nodeChanged( QSGNode* node, QSGNode::DirtyState state )
{ {
Inherited::nodeChanged( node, state );
/* /*
We want to limit updates to nodes, that are actually rendered. TODO ... No need to update the texture for changes of nodes behind
the final node.
In any case we need to block update requests, when the textureNode reports Unfortunately QQuickWindow does not update the scene graph in
that it has been updated by us to the renderer of the window. rendering order and we might be called for relevant nodes after
the texture has already been updated. In these situations we
update the texture twice. Not so good ...
*/ */
if ( ( state != QSGNode::DirtyMaterial ) if ( qskRenderOrderCompare( rootNode(), node, m_finalNode ) > 0 )
|| ( node != m_texture->textureNode() ) ) {
// triggering QSGRenderer::sceneGraphChanged signals
Inherited::nodeChanged( node, state );
}
}
void Renderer::markDirty()
{
if ( !m_dirty )
{ {
m_dirty = true; m_dirty = true;
Q_EMIT m_texture->updateRequested(); Q_EMIT m_texture->updateRequested();
@ -295,19 +348,44 @@ class QskSceneTexturePrivate final : public QSGTexturePrivate
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) #if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
int comparisonKey() const override int comparisonKey() const override
{ return int( qintptr( rhiTexture() ) ); } {
if ( renderer )
{
if ( renderer->textureId() )
return renderer->textureId();
if ( renderer->rhiTexture() )
return int( qintptr( renderer->rhiTexture() ) );
}
return int( qintptr( this ) );
}
QRhiTexture *rhiTexture() const override QRhiTexture *rhiTexture() const override
{ return renderer ? renderer->rhiTexture() : nullptr; } { return renderer ? renderer->rhiTexture() : nullptr; }
#endif #endif
QSize pixelSize() const
{
QSize size( qCeil( rect.width() ), qCeil( rect.height() ) );
size *= devicePixelRatio;
const QSize minSize = context->sceneGraphContext()->minimumFBOSize();
while ( size.width() < minSize.width() )
size.rwidth() *= 2;
while ( size.height() < minSize.height() )
size.rheight() *= 2;
return size;
}
QRectF rect; QRectF rect;
const qreal devicePixelRatio; const qreal devicePixelRatio;
Renderer* renderer = nullptr; Renderer* renderer = nullptr;
QSGDefaultRenderContext* context = nullptr; QSGDefaultRenderContext* context = nullptr;
const QSGGeometryNode* textureNode = nullptr;
}; };
QskSceneTexture::QskSceneTexture( const QQuickWindow* window ) QskSceneTexture::QskSceneTexture( const QQuickWindow* window )
@ -321,32 +399,10 @@ QskSceneTexture::~QskSceneTexture()
delete d_func()->renderer; delete d_func()->renderer;
} }
void QskSceneTexture::setTextureNode( const QSGGeometryNode* node )
{
d_func()->textureNode = node;
}
const QSGGeometryNode* QskSceneTexture::textureNode() const
{
return d_func()->textureNode;
}
QSize QskSceneTexture::textureSize() const QSize QskSceneTexture::textureSize() const
{ {
Q_D( const QskSceneTexture ); Q_D( const QskSceneTexture );
return d->renderer ? d->renderer->textureSize() : QSize();
QSize size( qCeil( d->rect.width() ), qCeil( d->rect.height() ) );
size *= d->devicePixelRatio;
const QSize minSize = d->context->sceneGraphContext()->minimumFBOSize();
while ( size.width() < minSize.width() )
size.rwidth() *= 2;
while ( size.height() < minSize.height() )
size.rheight() *= 2;
return size;
} }
void QskSceneTexture::render( const QSGRootNode* rootNode, void QskSceneTexture::render( const QSGRootNode* rootNode,
@ -366,7 +422,7 @@ void QskSceneTexture::render( const QSGRootNode* rootNode,
d->renderer->setFinalNode( const_cast< QSGTransformNode* >( finalNode ) ); d->renderer->setFinalNode( const_cast< QSGTransformNode* >( finalNode ) );
d->renderer->setProjection( d->rect ); d->renderer->setProjection( d->rect );
d->renderer->setTextureSize( textureSize() ); d->renderer->setTextureSize( d->pixelSize() );
d->renderer->renderScene(); d->renderer->renderScene();
} }

View File

@ -13,7 +13,6 @@ class QskSceneTexturePrivate;
class QSGRootNode; class QSGRootNode;
class QSGTransformNode; class QSGTransformNode;
class QSGGeometryNode;
class QQuickWindow; class QQuickWindow;
class QSK_EXPORT QskSceneTexture : public QSGTexture class QSK_EXPORT QskSceneTexture : public QSGTexture
@ -26,12 +25,6 @@ class QSK_EXPORT QskSceneTexture : public QSGTexture
QskSceneTexture( const QQuickWindow* ); QskSceneTexture( const QQuickWindow* );
~QskSceneTexture(); ~QskSceneTexture();
#if 1
// to avoid recursive update - need to find a better solution TODO
void setTextureNode( const QSGGeometryNode* );
const QSGGeometryNode* textureNode() const;
#endif
void render( const QSGRootNode*, const QSGTransformNode*, const QRectF& ); void render( const QSGRootNode*, const QSGTransformNode*, const QRectF& );
QSize textureSize() const override; QSize textureSize() const override;