using SceneTexture instead of QSGLayer. blocking the renderer hen
reaching the itemNode is not solved yet
This commit is contained in:
parent
162534c13c
commit
7615cffdd4
|
@ -6,6 +6,7 @@
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
Overlay.h Overlay.cpp
|
Overlay.h Overlay.cpp
|
||||||
BlurringNode.h BlurringNode.cpp
|
BlurringNode.h BlurringNode.cpp
|
||||||
|
SceneTexture.h SceneTexture.cpp
|
||||||
main.cpp)
|
main.cpp)
|
||||||
|
|
||||||
qt_add_resources(SOURCES images.qrc shaders.qrc)
|
qt_add_resources(SOURCES images.qrc shaders.qrc)
|
||||||
|
|
|
@ -5,10 +5,9 @@
|
||||||
|
|
||||||
#include "Overlay.h"
|
#include "Overlay.h"
|
||||||
#include "BlurringNode.h"
|
#include "BlurringNode.h"
|
||||||
|
#include "SceneTexture.h"
|
||||||
|
|
||||||
#include <private/qquickitem_p.h>
|
#include <private/qquickitem_p.h>
|
||||||
#include <private/qquickwindow_p.h>
|
|
||||||
#include <private/qsgadaptationlayer_p.h>
|
|
||||||
#include <private/qquickitemchangelistener_p.h>
|
#include <private/qquickitemchangelistener_p.h>
|
||||||
|
|
||||||
#include <qpointer.h>
|
#include <qpointer.h>
|
||||||
|
@ -43,22 +42,6 @@ class OverlayPrivate final : public QQuickItemPrivate, public QQuickItemChangeLi
|
||||||
q_func()->update();
|
q_func()->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCovering( bool on )
|
|
||||||
{
|
|
||||||
if ( on == covering )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ( grabbedItem )
|
|
||||||
{
|
|
||||||
auto sd = QQuickItemPrivate::get( grabbedItem );
|
|
||||||
|
|
||||||
sd->refFromEffectItem( on );
|
|
||||||
sd->derefFromEffectItem( covering );
|
|
||||||
}
|
|
||||||
|
|
||||||
covering = on;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setAttached( bool on )
|
void setAttached( bool on )
|
||||||
{
|
{
|
||||||
if ( grabbedItem )
|
if ( grabbedItem )
|
||||||
|
@ -67,76 +50,28 @@ class OverlayPrivate final : public QQuickItemPrivate, public QQuickItemChangeLi
|
||||||
|
|
||||||
if ( on )
|
if ( on )
|
||||||
{
|
{
|
||||||
d->refFromEffectItem( covering );
|
d->refFromEffectItem( false );
|
||||||
d->addItemChangeListener( this, Geometry );
|
d->addItemChangeListener( this, Geometry );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
d->removeItemChangeListener( this, Geometry );
|
d->removeItemChangeListener( this, Geometry );
|
||||||
d->derefFromEffectItem( covering );
|
d->derefFromEffectItem( false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGLayer* createTexture()
|
QSGRootNode* grabbedNode()
|
||||||
{
|
{
|
||||||
auto renderContext = sceneGraphRenderContext();
|
return grabbedItem ? get( grabbedItem )->rootNode() : nullptr;
|
||||||
|
|
||||||
auto layer = renderContext->sceneGraphContext()->createLayer( renderContext );
|
|
||||||
|
|
||||||
layer->setMipmapFiltering( QSGTexture::None );
|
|
||||||
layer->setHorizontalWrapMode( QSGTexture::ClampToEdge );
|
|
||||||
layer->setVerticalWrapMode( QSGTexture::ClampToEdge );
|
|
||||||
layer->setFormat( QSGLayer::RGBA8 );
|
|
||||||
layer->setHasMipmaps( false );
|
|
||||||
layer->setMirrorHorizontal( false );
|
|
||||||
layer->setMirrorVertical( true );
|
|
||||||
|
|
||||||
if ( q_func()->window()->format().samples() > 2 )
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
We want to disable multisampling as it doesn't make any sense
|
|
||||||
in combination with blurring afterwards. Unfortunately
|
|
||||||
QSGLayer uses the samples from the window when setting samples
|
|
||||||
below 2 here.
|
|
||||||
*/
|
|
||||||
layer->setSamples( 2 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return layer;
|
QSGTransformNode* grabbedItemNode()
|
||||||
}
|
|
||||||
|
|
||||||
void updateTexture( QSGLayer* layer )
|
|
||||||
{
|
{
|
||||||
Q_Q( Overlay );
|
return grabbedItem ? get( grabbedItem )->itemNode() : nullptr;
|
||||||
|
|
||||||
const auto pixelRatio = q->window()->effectiveDevicePixelRatio();
|
|
||||||
|
|
||||||
layer->setLive( true );
|
|
||||||
layer->setItem( QQuickItemPrivate::get( grabbedItem )->itemNode() );
|
|
||||||
|
|
||||||
const auto rect = QRectF( q->position(), q->size() );
|
|
||||||
layer->setRect( rect );
|
|
||||||
|
|
||||||
QSize textureSize( qCeil( rect.width() ), qCeil( rect.height() ) );
|
|
||||||
textureSize *= pixelRatio;
|
|
||||||
|
|
||||||
const QSize minTextureSize = sceneGraphContext()->minimumFBOSize();
|
|
||||||
|
|
||||||
while ( textureSize.width() < minTextureSize.width() )
|
|
||||||
textureSize.rwidth() *= 2;
|
|
||||||
|
|
||||||
while ( textureSize.height() < minTextureSize.height() )
|
|
||||||
textureSize.rheight() *= 2;
|
|
||||||
|
|
||||||
layer->setDevicePixelRatio( pixelRatio );
|
|
||||||
layer->setSize( textureSize );
|
|
||||||
layer->setRecursive( false );
|
|
||||||
layer->setFiltering( q->smooth() ? QSGTexture::Linear : QSGTexture::Nearest );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointer< QQuickItem > grabbedItem;
|
QPointer< QQuickItem > grabbedItem;
|
||||||
bool covering = false;
|
|
||||||
|
|
||||||
Q_DECLARE_PUBLIC(Overlay)
|
Q_DECLARE_PUBLIC(Overlay)
|
||||||
};
|
};
|
||||||
|
@ -176,36 +111,30 @@ void Overlay::geometryChange(
|
||||||
{
|
{
|
||||||
Inherited::geometryChange( newGeometry, oldGeometry );
|
Inherited::geometryChange( newGeometry, oldGeometry );
|
||||||
|
|
||||||
/*
|
|
||||||
When newGeometry covers the grabbedItem completely we could
|
|
||||||
set covering to true. TODO ...
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( d_func()->grabbedItem )
|
if ( d_func()->grabbedItem )
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGNode* Overlay::updatePaintNode( QSGNode* oldNode, UpdatePaintNodeData* )
|
QSGNode* Overlay::updatePaintNode( QSGNode* oldNode, UpdatePaintNodeData* )
|
||||||
{
|
{
|
||||||
if ( size().isEmpty() )
|
Q_D( Overlay );
|
||||||
|
|
||||||
|
if ( d->grabbedItemNode() == nullptr || size().isEmpty() )
|
||||||
{
|
{
|
||||||
delete oldNode;
|
delete oldNode;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_D( Overlay );
|
|
||||||
|
|
||||||
auto node = static_cast< BlurringNode* >( oldNode );
|
auto node = static_cast< BlurringNode* >( oldNode );
|
||||||
|
|
||||||
if ( node == nullptr )
|
if ( node == nullptr )
|
||||||
{
|
{
|
||||||
node = new BlurringNode();
|
node = new BlurringNode();
|
||||||
|
|
||||||
auto layer = d->createTexture();
|
auto texture = new SceneTexture( d->sceneGraphRenderContext() );
|
||||||
node->setTexture( layer );
|
texture->setDevicePixelRatio( window()->effectiveDevicePixelRatio() );
|
||||||
|
|
||||||
connect( layer, &QSGLayer::updateRequested,
|
node->setTexture( texture );
|
||||||
this, &QQuickItem::update );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto itemNode = static_cast< TransformNode* >( d->itemNode() );
|
auto itemNode = static_cast< TransformNode* >( d->itemNode() );
|
||||||
|
@ -214,12 +143,14 @@ QSGNode* Overlay::updatePaintNode( QSGNode* oldNode, UpdatePaintNodeData* )
|
||||||
{
|
{
|
||||||
itemNode->isBlocked = true;
|
itemNode->isBlocked = true;
|
||||||
|
|
||||||
auto layer = static_cast< QSGLayer* >( node->texture() );
|
auto texture = static_cast< SceneTexture* >( node->texture() );
|
||||||
|
texture->setFiltering( smooth() ? QSGTexture::Linear : QSGTexture::Nearest );
|
||||||
|
|
||||||
d->updateTexture( layer );
|
texture->render( d->grabbedNode(), itemNode,
|
||||||
|
QRectF( x(), y(), width(), height() ) );
|
||||||
|
|
||||||
layer->updateTexture();
|
|
||||||
itemNode->isBlocked = false;
|
itemNode->isBlocked = false;
|
||||||
|
QMetaObject::invokeMethod( this, &QQuickItem::update );
|
||||||
}
|
}
|
||||||
|
|
||||||
node->setRect( QRectF( 0, 0, width(), height() ) );
|
node->setRect( QRectF( 0, 0, width(), height() ) );
|
||||||
|
|
|
@ -0,0 +1,219 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "SceneTexture.h"
|
||||||
|
#include <private/qsgbatchrenderer_p.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class Renderer : public QSGBatchRenderer::Renderer
|
||||||
|
{
|
||||||
|
using Inherited = QSGBatchRenderer::Renderer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Renderer( QSGDefaultRenderContext* context )
|
||||||
|
: Inherited( context, renderMode( context ) )
|
||||||
|
{
|
||||||
|
setClearColor( Qt::transparent );
|
||||||
|
}
|
||||||
|
|
||||||
|
~Renderer() override
|
||||||
|
{
|
||||||
|
clearTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFinalNode( QSGTransformNode* node )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
we need to find a way how to block all nodes
|
||||||
|
that are rendered behing m_finalNode TODO ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
m_finalNode = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRhiTexture* texture() const { return m_rhiTexture; }
|
||||||
|
|
||||||
|
void setProjection( const QRectF& rect )
|
||||||
|
{
|
||||||
|
const auto rhi = context()->rhi();
|
||||||
|
|
||||||
|
auto r = rect;
|
||||||
|
|
||||||
|
if ( rhi->isYUpInFramebuffer() )
|
||||||
|
{
|
||||||
|
r.moveTop( r.bottom() );
|
||||||
|
r.setHeight( -r.height() );
|
||||||
|
}
|
||||||
|
|
||||||
|
MatrixTransformFlags matrixFlags;
|
||||||
|
|
||||||
|
if ( !rhi->isYUpInNDC() )
|
||||||
|
matrixFlags |= QSGAbstractRenderer::MatrixTransformFlipY;
|
||||||
|
|
||||||
|
setProjectionMatrixToRect( r, matrixFlags );
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTextureSize( const QSize& size )
|
||||||
|
{
|
||||||
|
if ( m_rt.rt && m_rt.rt->pixelSize() != size )
|
||||||
|
clearTarget();
|
||||||
|
|
||||||
|
if ( m_rt.rt == nullptr )
|
||||||
|
createTarget( size );
|
||||||
|
|
||||||
|
const QRect r( 0, 0, size.width(), size.height() );
|
||||||
|
|
||||||
|
setDeviceRect( r );
|
||||||
|
setViewportRect( r );
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderScene() override
|
||||||
|
{
|
||||||
|
Inherited::renderScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createTarget( const QSize& size )
|
||||||
|
{
|
||||||
|
const auto rhi = context()->rhi();
|
||||||
|
|
||||||
|
auto flags = QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource;
|
||||||
|
|
||||||
|
m_rhiTexture = rhi->newTexture( QRhiTexture::RGBA8, size, 1, flags );
|
||||||
|
m_rhiTexture->create();
|
||||||
|
|
||||||
|
QRhiColorAttachment color0( m_rhiTexture );
|
||||||
|
auto target = rhi->newTextureRenderTarget( { color0 } );
|
||||||
|
|
||||||
|
target->setRenderPassDescriptor(
|
||||||
|
target->newCompatibleRenderPassDescriptor() );
|
||||||
|
|
||||||
|
target->create();
|
||||||
|
|
||||||
|
m_rt.rt = target;
|
||||||
|
m_rt.rpDesc = target->renderPassDescriptor();
|
||||||
|
|
||||||
|
auto defaultContext = qobject_cast< QSGDefaultRenderContext* >( context() );
|
||||||
|
m_rt.cb = defaultContext->currentFrameCommandBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearTarget()
|
||||||
|
{
|
||||||
|
delete m_rt.rt;
|
||||||
|
m_rt.rt = nullptr;
|
||||||
|
|
||||||
|
delete m_rt.rpDesc;
|
||||||
|
m_rt.rpDesc = nullptr;
|
||||||
|
|
||||||
|
delete m_rhiTexture;
|
||||||
|
m_rhiTexture = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nodeChanged( QSGNode* node, QSGNode::DirtyState state ) override
|
||||||
|
{
|
||||||
|
Inherited::nodeChanged( node, state );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline QSGRendererInterface::RenderMode renderMode(
|
||||||
|
QSGDefaultRenderContext* context ) const
|
||||||
|
{
|
||||||
|
return context->useDepthBufferFor2D()
|
||||||
|
? QSGRendererInterface::RenderMode2D
|
||||||
|
: QSGRendererInterface::RenderMode2DNoDepthBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRhiTexture* m_rhiTexture = nullptr;
|
||||||
|
QSGTransformNode* m_finalNode = nullptr;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class SceneTexturePrivate final : public QSGTexturePrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SceneTexturePrivate( SceneTexture* texture )
|
||||||
|
: QSGTexturePrivate( texture )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF rect;
|
||||||
|
qreal devicePixelRatio = 1.0;
|
||||||
|
|
||||||
|
Renderer* renderer = nullptr;
|
||||||
|
QSGDefaultRenderContext* context = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
SceneTexture::SceneTexture( QSGRenderContext* context )
|
||||||
|
: Inherited(*( new SceneTexturePrivate(this) ) )
|
||||||
|
{
|
||||||
|
d_func()->context = static_cast< QSGDefaultRenderContext* >( context );
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneTexture::~SceneTexture()
|
||||||
|
{
|
||||||
|
delete d_func()->renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize SceneTexture::textureSize() const
|
||||||
|
{
|
||||||
|
Q_D( const SceneTexture );
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 SceneTexture::comparisonKey() const
|
||||||
|
{
|
||||||
|
return qint64( rhiTexture() );
|
||||||
|
}
|
||||||
|
|
||||||
|
QRhiTexture* SceneTexture::rhiTexture() const
|
||||||
|
{
|
||||||
|
Q_D( const SceneTexture );
|
||||||
|
return d->renderer ? d->renderer->texture() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneTexture::render( QSGRootNode* rootNode,
|
||||||
|
QSGTransformNode* finalNode, const QRectF& rect )
|
||||||
|
{
|
||||||
|
Q_D( SceneTexture );
|
||||||
|
|
||||||
|
d->rect = rect;
|
||||||
|
|
||||||
|
const auto pixelSize = textureSize();
|
||||||
|
|
||||||
|
if ( d->renderer == nullptr )
|
||||||
|
{
|
||||||
|
d->renderer = new Renderer( d->context );
|
||||||
|
d->renderer->setDevicePixelRatio( d->devicePixelRatio );
|
||||||
|
}
|
||||||
|
|
||||||
|
d->renderer->setRootNode( rootNode );
|
||||||
|
d->renderer->setFinalNode( finalNode );
|
||||||
|
d->renderer->setProjection( d->rect );
|
||||||
|
d->renderer->setTextureSize( pixelSize );
|
||||||
|
d->renderer->renderScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneTexture::setDevicePixelRatio( qreal ratio )
|
||||||
|
{
|
||||||
|
d_func()->devicePixelRatio = ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF SceneTexture::normalizedTextureSubRect() const
|
||||||
|
{
|
||||||
|
return QRectF( 0, 1, 1, -1 );
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <qsgtexture.h>
|
||||||
|
|
||||||
|
class SceneTexturePrivate;
|
||||||
|
class QSGRenderContext;
|
||||||
|
|
||||||
|
class QSGRootNode;
|
||||||
|
class QSGTransformNode;
|
||||||
|
|
||||||
|
class SceneTexture : public QSGTexture
|
||||||
|
{
|
||||||
|
using Inherited = QSGTexture;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SceneTexture( QSGRenderContext* );
|
||||||
|
~SceneTexture();
|
||||||
|
|
||||||
|
void setDevicePixelRatio( qreal );
|
||||||
|
void render( QSGRootNode*, QSGTransformNode*, const QRectF& );
|
||||||
|
|
||||||
|
QSize textureSize() const override;
|
||||||
|
|
||||||
|
qint64 comparisonKey() const override;
|
||||||
|
QRhiTexture* rhiTexture() const override;
|
||||||
|
|
||||||
|
QRectF normalizedTextureSubRect() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// nops to satisfy the QSGTexture API
|
||||||
|
bool hasAlphaChannel() const override { return true; }
|
||||||
|
bool hasMipmaps() const override { return false; }
|
||||||
|
void commitTextureOperations( QRhi*, QRhiResourceUpdateBatch* ) override {}
|
||||||
|
|
||||||
|
Q_DECLARE_PRIVATE( SceneTexture )
|
||||||
|
};
|
|
@ -137,8 +137,13 @@ class MainView : public QskControl
|
||||||
m_background = new BackgroundItem( this );
|
m_background = new BackgroundItem( this );
|
||||||
|
|
||||||
m_overlay = new OverlayBox( m_background );
|
m_overlay = new OverlayBox( m_background );
|
||||||
|
|
||||||
(void )new ButtonBox( m_overlay );
|
(void )new ButtonBox( m_overlay );
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
auto box = new QskBox( m_background );
|
||||||
|
box->setGeometry( 50, 50, 400, 200 );
|
||||||
|
box->setFillGradient( Qt::darkBlue );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
Loading…
Reference in New Issue