QskSceneTexture added
This commit is contained in:
parent
bdf4bb045c
commit
fb3d09430f
@ -120,6 +120,7 @@ list(APPEND HEADERS
|
||||
nodes/QskPaintedNode.h
|
||||
nodes/QskPlainTextRenderer.h
|
||||
nodes/QskRichTextRenderer.h
|
||||
nodes/QskSceneTexture.h
|
||||
nodes/QskSGNode.h
|
||||
nodes/QskStrokeNode.h
|
||||
nodes/QskStippledLineRenderer.h
|
||||
@ -157,6 +158,7 @@ list(APPEND SOURCES
|
||||
nodes/QskPlainTextRenderer.cpp
|
||||
nodes/QskRectangleNode.cpp
|
||||
nodes/QskRichTextRenderer.cpp
|
||||
nodes/QskSceneTexture.cpp
|
||||
nodes/QskSGNode.cpp
|
||||
nodes/QskStrokeNode.cpp
|
||||
nodes/QskStippledLineRenderer.cpp
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qquickitem_p.h>
|
||||
#include <private/qquickwindow_p.h>
|
||||
#include <private/qsgrenderer_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
#include <qpa/qplatforminputcontext.h>
|
||||
@ -387,6 +389,48 @@ const QSGNode* qskPaintNode( const QQuickItem* item )
|
||||
return QQuickItemPrivate::get( item )->paintNode;
|
||||
}
|
||||
|
||||
const QSGRootNode* qskScenegraphAnchorNode( const QQuickItem* item )
|
||||
{
|
||||
if ( item == nullptr )
|
||||
return nullptr;
|
||||
|
||||
return QQuickItemPrivate::get( item )->rootNode();
|
||||
}
|
||||
|
||||
const QSGRootNode* qskScenegraphAnchorNode( const QQuickWindow* window )
|
||||
{
|
||||
if ( window )
|
||||
{
|
||||
if ( auto renderer = QQuickWindowPrivate::get( window )->renderer )
|
||||
return renderer->rootNode();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void qskSetScenegraphAnchor( QQuickItem* item, bool on )
|
||||
{
|
||||
/*
|
||||
For setting up a subtree renderer ( f.e in QskSceneTexture ) we need
|
||||
to insert a QSGRootNode above the paintNode.
|
||||
|
||||
( In Qt this feature is exlusively used in the Qt/Quick Effects module
|
||||
what lead to the not very intuitive name "refFromEffectItem" )
|
||||
|
||||
refFromEffectItem also allows to insert a opacity node of 0 to
|
||||
hide the subtree from the main renderer by setting its parameter to
|
||||
true. We have QskItemNode to achieve the same.
|
||||
*/
|
||||
if ( item )
|
||||
{
|
||||
auto d = QQuickItemPrivate::get( item );
|
||||
if ( on )
|
||||
d->refFromEffectItem( false );
|
||||
else
|
||||
d->derefFromEffectItem( false );
|
||||
}
|
||||
}
|
||||
|
||||
QSizeF qskEffectiveSizeHint( const QQuickItem* item,
|
||||
Qt::SizeHint whichHint, const QSizeF& constraint )
|
||||
{
|
||||
|
@ -14,10 +14,11 @@
|
||||
|
||||
class QskSizePolicy;
|
||||
|
||||
class QQuickItem;
|
||||
class QSGNode;
|
||||
class QSGTransformNode;
|
||||
class QSGRootNode;
|
||||
class QRectF;
|
||||
|
||||
template< typename T > class QList;
|
||||
|
||||
/*
|
||||
@ -71,6 +72,10 @@ QSK_EXPORT void qskInputMethodSetVisible( const QQuickItem*, bool );
|
||||
QSK_EXPORT const QSGTransformNode* qskItemNode( const QQuickItem* );
|
||||
QSK_EXPORT const QSGNode* qskPaintNode( const QQuickItem* );
|
||||
|
||||
QSK_EXPORT const QSGRootNode* qskScenegraphAnchorNode( const QQuickItem* );
|
||||
QSK_EXPORT const QSGRootNode* qskScenegraphAnchorNode( const QQuickWindow* );
|
||||
QSK_EXPORT void qskSetScenegraphAnchor( QQuickItem*, bool on, bool hide = false );
|
||||
|
||||
QSK_EXPORT void qskItemUpdateRecursive( QQuickItem* );
|
||||
|
||||
QSK_EXPORT bool qskGrabMouse( QQuickItem* );
|
||||
|
268
src/nodes/QskSceneTexture.cpp
Normal file
268
src/nodes/QskSceneTexture.cpp
Normal file
@ -0,0 +1,268 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskSceneTexture.h"
|
||||
#include "QskTreeNode.h"
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qquickwindow_p.h>
|
||||
#include <private/qsgbatchrenderer_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
namespace
|
||||
{
|
||||
inline QSGRendererInterface::RenderMode contextRenderMode(
|
||||
QSGDefaultRenderContext* context )
|
||||
{
|
||||
return context->useDepthBufferFor2D()
|
||||
? QSGRendererInterface::RenderMode2D
|
||||
: QSGRendererInterface::RenderMode2DNoDepthBuffer;
|
||||
}
|
||||
|
||||
class Renderer final : public QSGBatchRenderer::Renderer
|
||||
{
|
||||
using Inherited = QSGBatchRenderer::Renderer;
|
||||
|
||||
public:
|
||||
Renderer( QskSceneTexture*, QSGDefaultRenderContext* );
|
||||
~Renderer() override;
|
||||
|
||||
void setFinalNode( QSGTransformNode* );
|
||||
QRhiTexture* texture() const { return m_rhiTexture; }
|
||||
|
||||
void setProjection( const QRectF& );
|
||||
void setTextureSize( const QSize& );
|
||||
|
||||
protected:
|
||||
void nodeChanged( QSGNode*, QSGNode::DirtyState ) override;
|
||||
void render() override;
|
||||
|
||||
private:
|
||||
void createTarget( const QSize& );
|
||||
void clearTarget();
|
||||
|
||||
private:
|
||||
QRhiTexture* m_rhiTexture = nullptr;
|
||||
QSGTransformNode* m_finalNode = nullptr;
|
||||
|
||||
QskSceneTexture* m_texture = nullptr;
|
||||
};
|
||||
|
||||
Renderer::Renderer( QskSceneTexture* texture, QSGDefaultRenderContext* context )
|
||||
: Inherited( context, contextRenderMode( context ) )
|
||||
, m_texture( texture )
|
||||
{
|
||||
setClearColor( Qt::transparent );
|
||||
}
|
||||
|
||||
Renderer::~Renderer()
|
||||
{
|
||||
clearTarget();
|
||||
}
|
||||
|
||||
void Renderer::setFinalNode( QSGTransformNode* node )
|
||||
{
|
||||
if ( node != m_finalNode )
|
||||
{
|
||||
m_finalNode = node;
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::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 Renderer::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 Renderer::render()
|
||||
{
|
||||
qskTryBlockTrailingNodes( m_finalNode, rootNode(), true, false );
|
||||
#if 0
|
||||
QSGNodeDumper::dump( rootNode() );
|
||||
#endif
|
||||
Inherited::render();
|
||||
qskTryBlockTrailingNodes( m_finalNode, rootNode(), false, false );
|
||||
}
|
||||
|
||||
void Renderer::nodeChanged( QSGNode* node, QSGNode::DirtyState state )
|
||||
{
|
||||
// do not forward nodes that are blocked while rendering
|
||||
|
||||
const bool isTrailingNode = false; // TODO ...
|
||||
|
||||
if ( !isTrailingNode )
|
||||
{
|
||||
Inherited::nodeChanged( node, state );
|
||||
Q_EMIT m_texture->updateRequested();
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::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 Renderer::clearTarget()
|
||||
{
|
||||
delete m_rt.rt;
|
||||
m_rt.rt = nullptr;
|
||||
|
||||
delete m_rt.rpDesc;
|
||||
m_rt.rpDesc = nullptr;
|
||||
|
||||
delete m_rhiTexture;
|
||||
m_rhiTexture = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
class QskSceneTexturePrivate final : public QSGTexturePrivate
|
||||
{
|
||||
public:
|
||||
QskSceneTexturePrivate( const QQuickWindow* window, QskSceneTexture* texture )
|
||||
: QSGTexturePrivate( texture )
|
||||
, devicePixelRatio( window->effectiveDevicePixelRatio() )
|
||||
{
|
||||
context = dynamic_cast< QSGDefaultRenderContext* >(
|
||||
QQuickWindowPrivate::get( window )->context );
|
||||
}
|
||||
|
||||
QRectF rect;
|
||||
const qreal devicePixelRatio;
|
||||
|
||||
Renderer* renderer = nullptr;
|
||||
QSGDefaultRenderContext* context = nullptr;
|
||||
};
|
||||
|
||||
QskSceneTexture::QskSceneTexture( const QQuickWindow* window )
|
||||
: Inherited(*( new QskSceneTexturePrivate( window, this ) ) )
|
||||
{
|
||||
Q_ASSERT( d_func()->context );
|
||||
}
|
||||
|
||||
QskSceneTexture::~QskSceneTexture()
|
||||
{
|
||||
delete d_func()->renderer;
|
||||
}
|
||||
|
||||
QSize QskSceneTexture::textureSize() const
|
||||
{
|
||||
Q_D( const QskSceneTexture );
|
||||
|
||||
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 QskSceneTexture::comparisonKey() const
|
||||
{
|
||||
return qint64( rhiTexture() );
|
||||
}
|
||||
|
||||
QRhiTexture* QskSceneTexture::rhiTexture() const
|
||||
{
|
||||
Q_D( const QskSceneTexture );
|
||||
return d->renderer ? d->renderer->texture() : nullptr;
|
||||
}
|
||||
|
||||
void QskSceneTexture::render( const QSGRootNode* rootNode,
|
||||
const QSGTransformNode* finalNode, const QRectF& rect )
|
||||
{
|
||||
Q_D( QskSceneTexture );
|
||||
|
||||
d->rect = rect;
|
||||
|
||||
const auto pixelSize = textureSize();
|
||||
|
||||
if ( d->renderer == nullptr )
|
||||
{
|
||||
d->renderer = new Renderer( this, d->context );
|
||||
d->renderer->setDevicePixelRatio( d->devicePixelRatio );
|
||||
}
|
||||
|
||||
d->renderer->setRootNode( const_cast< QSGRootNode* >( rootNode ) );
|
||||
d->renderer->setFinalNode( const_cast< QSGTransformNode* >( finalNode ) );
|
||||
|
||||
d->renderer->setProjection( d->rect );
|
||||
d->renderer->setTextureSize( pixelSize );
|
||||
d->renderer->renderScene();
|
||||
}
|
||||
|
||||
QRectF QskSceneTexture::normalizedTextureSubRect() const
|
||||
{
|
||||
return QRectF( 0, 1, 1, -1 );
|
||||
}
|
||||
|
||||
bool QskSceneTexture::hasAlphaChannel() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QskSceneTexture::hasMipmaps() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void QskSceneTexture::commitTextureOperations( QRhi*, QRhiResourceUpdateBatch* )
|
||||
{
|
||||
// what to do here ?
|
||||
}
|
||||
|
||||
#include "moc_QskSceneTexture.cpp"
|
49
src/nodes/QskSceneTexture.h
Normal file
49
src/nodes/QskSceneTexture.h
Normal file
@ -0,0 +1,49 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QSK_SCENE_TEXTURE_H
|
||||
#define QSK_SCENE_TEXTURE_H
|
||||
|
||||
#include "QskGlobal.h"
|
||||
#include <qsgtexture.h>
|
||||
|
||||
class QskSceneTexturePrivate;
|
||||
|
||||
class QSGRootNode;
|
||||
class QSGTransformNode;
|
||||
class QQuickWindow;
|
||||
|
||||
class QSK_EXPORT QskSceneTexture : public QSGTexture
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
using Inherited = QSGTexture;
|
||||
|
||||
public:
|
||||
QskSceneTexture( const QQuickWindow* );
|
||||
~QskSceneTexture();
|
||||
|
||||
void render( const QSGRootNode*, const QSGTransformNode*, const QRectF& );
|
||||
|
||||
QSize textureSize() const override;
|
||||
|
||||
qint64 comparisonKey() const override;
|
||||
QRhiTexture* rhiTexture() const override;
|
||||
|
||||
QRectF normalizedTextureSubRect() const override;
|
||||
|
||||
// satisfy the QSGTexture API
|
||||
bool hasAlphaChannel() const override;
|
||||
bool hasMipmaps() const override;
|
||||
void commitTextureOperations( QRhi*, QRhiResourceUpdateBatch* ) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void updateRequested();
|
||||
|
||||
private:
|
||||
Q_DECLARE_PRIVATE( QskSceneTexture )
|
||||
};
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user