seems to work now - even when being a child

This commit is contained in:
Uwe Rathmann 2023-12-08 15:35:34 +01:00
parent 725500fdaf
commit ff1b479938
4 changed files with 54 additions and 98 deletions

View File

@ -91,7 +91,17 @@ class BlurredOverlayPrivate final : public QQuickItemPrivate, public QQuickItemC
layer->setHasMipmaps( false ); layer->setHasMipmaps( false );
layer->setMirrorHorizontal( false ); layer->setMirrorHorizontal( false );
layer->setMirrorVertical( true ); layer->setMirrorVertical( true );
layer->setSamples( 0 );
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; return layer;
} }
@ -100,19 +110,15 @@ class BlurredOverlayPrivate final : public QQuickItemPrivate, public QQuickItemC
{ {
Q_Q( BlurredOverlay ); Q_Q( BlurredOverlay );
layer->setLive( live ); const auto pixelRatio = q->window()->effectiveDevicePixelRatio();
layer->setLive( true );
layer->setItem( QQuickItemPrivate::get( grabbedItem )->itemNode() ); layer->setItem( QQuickItemPrivate::get( grabbedItem )->itemNode() );
auto r = grabRect; const auto rect = QRectF( q->position(), q->size() );
if ( r.isEmpty() ) layer->setRect( rect );
r = QRectF(0, 0, grabbedItem->width(), grabbedItem->height() );
layer->setRect( r ); QSize textureSize( qCeil( rect.width() ), qCeil( rect.height() ) );
QSize textureSize( qCeil( qAbs( r.width() ) ),
qCeil( qAbs( r.height() ) ) );
const auto pixelRatio = q->window()->effectiveDevicePixelRatio();
textureSize *= pixelRatio; textureSize *= pixelRatio;
const QSize minTextureSize = sceneGraphContext()->minimumFBOSize(); const QSize minTextureSize = sceneGraphContext()->minimumFBOSize();
@ -130,10 +136,7 @@ class BlurredOverlayPrivate final : public QQuickItemPrivate, public QQuickItemC
} }
QPointer< QQuickItem > grabbedItem; QPointer< QQuickItem > grabbedItem;
QRectF grabRect; bool covering = false;
const bool live = true;
bool covering = true;
Q_DECLARE_PUBLIC(BlurredOverlay) Q_DECLARE_PUBLIC(BlurredOverlay)
}; };
@ -169,41 +172,18 @@ void BlurredOverlay::setGrabbedItem( QQuickItem* item )
update(); update();
} }
QRectF BlurredOverlay::grabRect() const
{
return d_func()->grabRect;
}
void BlurredOverlay::setGrabRect( const QRectF& rect )
{
Q_D( BlurredOverlay );
QRectF r;
if ( !rect.isEmpty() )
r = rect;
if ( r == d->grabRect )
return;
if ( r.isEmpty() != d->grabRect.isEmpty() )
d->setCovering( r.isEmpty() );
d->grabRect = r;
if ( d->grabbedItem )
update();
}
void BlurredOverlay::resetGrabRect()
{
setGrabRect( QRectF() );
}
void BlurredOverlay::geometryChange( void BlurredOverlay::geometryChange(
const QRectF& newGeometry, const QRectF& oldGeometry ) const QRectF& newGeometry, const QRectF& oldGeometry )
{ {
update();
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 )
update();
} }
QSGNode* BlurredOverlay::updatePaintNode( QSGNode* oldNode, UpdatePaintNodeData* ) QSGNode* BlurredOverlay::updatePaintNode( QSGNode* oldNode, UpdatePaintNodeData* )
@ -229,22 +209,16 @@ QSGNode* BlurredOverlay::updatePaintNode( QSGNode* oldNode, UpdatePaintNodeData*
this, &QQuickItem::update ); this, &QQuickItem::update );
} }
auto layer = static_cast< QSGLayer* >( node->texture() ); auto itemNode = static_cast< TransformNode* >( d->itemNode() );
d->updateTexture( layer );
if ( !itemNode->isBlocked )
{ {
auto itemNode = static_cast< TransformNode* >( d->itemNode() );
/*
When we are a child of grabbedItem we end up in a recursion
that fails when initializing the texture twice. No problem
as we explicitly do not want to become part of it.
Disabling our subtree avoids the problem with the initialization
- the texture contains some artifacts from our own children. TODO ...
*/
itemNode->isBlocked = true; itemNode->isBlocked = true;
auto layer = static_cast< QSGLayer* >( node->texture() );
d->updateTexture( layer );
layer->updateTexture(); layer->updateTexture();
itemNode->isBlocked = false; itemNode->isBlocked = false;
} }

View File

@ -22,10 +22,6 @@ class BlurredOverlay : public QQuickItem
QQuickItem* grabbedItem() const; QQuickItem* grabbedItem() const;
void setGrabbedItem( QQuickItem* ); void setGrabbedItem( QQuickItem* );
QRectF grabRect() const;
void setGrabRect( const QRectF& );
void resetGrabRect();
protected: protected:
void geometryChange( const QRectF&, const QRectF& ) override; void geometryChange( const QRectF&, const QRectF& ) override;
QSGNode* updatePaintNode( QSGNode*, UpdatePaintNodeData* ) override; QSGNode* updatePaintNode( QSGNode*, UpdatePaintNodeData* ) override;

View File

@ -58,6 +58,10 @@ namespace
{ {
setFlag( UpdatesGraphicsPipelineState, true ); setFlag( UpdatesGraphicsPipelineState, true );
/*
Using our own shaders - we do not want to add a dependency
to the quickeffects module.
*/
setShaderFileName( VertexStage, ":/shaders/blur.vert.qsb" ); setShaderFileName( VertexStage, ":/shaders/blur.vert.qsb" );
setShaderFileName( FragmentStage, ":/shaders/blur.frag.qsb" ); setShaderFileName( FragmentStage, ":/shaders/blur.frag.qsb" );
} }

View File

@ -37,7 +37,6 @@ class ButtonBox : public QskLinearBox
label->setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); label->setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
label->setLayoutAlignmentHint( Qt::AlignCenter ); label->setLayoutAlignmentHint( Qt::AlignCenter );
auto button = new QskPushButton( "Button", this ); auto button = new QskPushButton( "Button", this );
button->setLayoutAlignmentHint( Qt::AlignHCenter | Qt::AlignBottom ); button->setLayoutAlignmentHint( Qt::AlignHCenter | Qt::AlignBottom );
} }
@ -57,33 +56,21 @@ class Overlay : public BlurredOverlay
void geometryChange( const QRectF& newRect, const QRectF& oldRect ) override void geometryChange( const QRectF& newRect, const QRectF& oldRect ) override
{ {
Inherited::geometryChange( newRect, oldRect ); Inherited::geometryChange( newRect, oldRect );
setGrabRect( grabbedItem()->mapRectFromItem( this, newRect ) );
const auto rect = qskItemRect( this );
const auto children = childItems();
for ( auto child : children )
{
if ( qskIsAdjustableByLayout( child ) )
{
const auto r = qskConstrainedItemRect( child, rect );
qskSetItemGeometry( child, r );
}
}
} }
}; };
class BlurredBox : public QskControl
{
using Inherited = QskControl;
public:
BlurredBox( QQuickItem* parent = nullptr )
: QskControl( parent )
{
setFlag( QQuickItem::ItemHasContents, false );
setAutoLayoutChildren( true );
m_overlay = new Overlay( this );
}
void setGrabbedItem( QQuickItem* item )
{
m_overlay->setGrabbedItem( item );
}
private:
Overlay* m_overlay;
};
class BackgroundItem : public QskControl class BackgroundItem : public QskControl
{ {
using Inherited = QskControl; using Inherited = QskControl;
@ -147,15 +134,10 @@ class MainView : public QskControl
m_background = new BackgroundItem( this ); m_background = new BackgroundItem( this );
#if 1 m_overlay = new Overlay( m_background );
m_blurredBox = new BlurredBox( this ); m_overlay->setGrabbedItem( m_background );
#else
// unsatisfying: see comment in BlurredOverlay::updatePaintNode TODO ...
m_blurredBox = new BlurredBox( m_background );
#endif
m_blurredBox->setGrabbedItem( m_background );
(void )new ButtonBox( m_blurredBox ); (void )new ButtonBox( m_overlay );
} }
protected: protected:
@ -166,12 +148,12 @@ class MainView : public QskControl
QRectF blurredRect( QPointF(), 0.7 * size() ); QRectF blurredRect( QPointF(), 0.7 * size() );
blurredRect.moveCenter( rect().center() ); blurredRect.moveCenter( rect().center() );
m_blurredBox->setGeometry( blurredRect ); qskSetItemGeometry( m_overlay, blurredRect );
} }
private: private:
BackgroundItem* m_background; BackgroundItem* m_background;
BlurredBox* m_blurredBox; Overlay* m_overlay;
}; };
int main( int argc, char** argv ) int main( int argc, char** argv )