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->setMirrorHorizontal( false );
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;
}
@ -100,19 +110,15 @@ class BlurredOverlayPrivate final : public QQuickItemPrivate, public QQuickItemC
{
Q_Q( BlurredOverlay );
layer->setLive( live );
const auto pixelRatio = q->window()->effectiveDevicePixelRatio();
layer->setLive( true );
layer->setItem( QQuickItemPrivate::get( grabbedItem )->itemNode() );
auto r = grabRect;
if ( r.isEmpty() )
r = QRectF(0, 0, grabbedItem->width(), grabbedItem->height() );
const auto rect = QRectF( q->position(), q->size() );
layer->setRect( rect );
layer->setRect( r );
QSize textureSize( qCeil( qAbs( r.width() ) ),
qCeil( qAbs( r.height() ) ) );
const auto pixelRatio = q->window()->effectiveDevicePixelRatio();
QSize textureSize( qCeil( rect.width() ), qCeil( rect.height() ) );
textureSize *= pixelRatio;
const QSize minTextureSize = sceneGraphContext()->minimumFBOSize();
@ -130,10 +136,7 @@ class BlurredOverlayPrivate final : public QQuickItemPrivate, public QQuickItemC
}
QPointer< QQuickItem > grabbedItem;
QRectF grabRect;
const bool live = true;
bool covering = true;
bool covering = false;
Q_DECLARE_PUBLIC(BlurredOverlay)
};
@ -169,41 +172,18 @@ void BlurredOverlay::setGrabbedItem( QQuickItem* item )
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(
const QRectF& newGeometry, const QRectF& oldGeometry )
{
update();
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* )
@ -229,22 +209,16 @@ QSGNode* BlurredOverlay::updatePaintNode( QSGNode* oldNode, UpdatePaintNodeData*
this, &QQuickItem::update );
}
auto layer = static_cast< QSGLayer* >( node->texture() );
d->updateTexture( layer );
auto itemNode = static_cast< TransformNode* >( d->itemNode() );
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;
auto layer = static_cast< QSGLayer* >( node->texture() );
d->updateTexture( layer );
layer->updateTexture();
itemNode->isBlocked = false;
}

View File

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

View File

@ -58,6 +58,10 @@ namespace
{
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( FragmentStage, ":/shaders/blur.frag.qsb" );
}

View File

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