From 738de14d4c47d57c7a2716cae32eb3d68eec18ba Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 13 Dec 2021 16:43:34 +0100 Subject: [PATCH] hiding the devicePixelRato scaling in the nodes --- examples/gbenchmark/Benchmark.cpp | 4 +- src/controls/QskSkinlet.cpp | 51 +++++++++++------------- src/graphic/QskGraphicTextureFactory.cpp | 2 +- src/nodes/QskGraphicNode.cpp | 2 +- src/nodes/QskPaintedNode.cpp | 2 +- src/nodes/QskTextureNode.cpp | 16 ++------ src/nodes/QskTextureRenderer.cpp | 35 +++++++++++----- src/nodes/QskTextureRenderer.h | 5 ++- 8 files changed, 61 insertions(+), 56 deletions(-) diff --git a/examples/gbenchmark/Benchmark.cpp b/examples/gbenchmark/Benchmark.cpp index 5fbdc23f..eeef334a 100644 --- a/examples/gbenchmark/Benchmark.cpp +++ b/examples/gbenchmark/Benchmark.cpp @@ -125,7 +125,7 @@ bool Benchmark::run( const QString& dirName ) using namespace QskTextureRenderer; const auto textureId = createTextureFromGraphic( - OpenGL, targetSize, graphics[ i ], colorFilter, + nullptr, OpenGL, targetSize, graphics[ i ], colorFilter, Qt::IgnoreAspectRatio ); if ( textureId == 0 ) @@ -151,7 +151,7 @@ bool Benchmark::run( const QString& dirName ) using namespace QskTextureRenderer; const auto textureId = createTextureFromGraphic( - Raster, targetSize, graphics[ i ], colorFilter, + nullptr, Raster, targetSize, graphics[ i ], colorFilter, Qt::IgnoreAspectRatio ); if ( textureId == 0 ) diff --git a/src/controls/QskSkinlet.cpp b/src/controls/QskSkinlet.cpp index a2606aac..3cdc2648 100644 --- a/src/controls/QskSkinlet.cpp +++ b/src/controls/QskSkinlet.cpp @@ -26,6 +26,28 @@ #include #include +static inline QRectF qskSceneAlignedRect( const QQuickItem* item , const QRectF& rect ) +{ + /* + Aligning rect according to scene coordinates, so that + we don't run into rounding issues downstream, where values + will be floored/ceiled ending up with a slightly different + aspect ratio. + */ + + const auto ratio = item->window()->devicePixelRatio(); + + const auto pos = item->mapToScene( rect.topLeft() ) * ratio; + const auto size = rect.size() * ratio; + + const qreal x = qRound( pos.x() ) / ratio; + const qreal y = qRound( pos.y() ) / ratio; + const qreal w = qRound( size.width() ) / ratio; + const qreal h = qRound( size.height() ) / ratio; + + return QRectF( item->mapFromScene( QPointF( x, y ) ), QSizeF( w, h ) ); +} + static inline QRectF qskSubControlRect( const QskSkinlet* skinlet, const QskSkinnable* skinnable, QskAspect::Subcontrol subControl ) { @@ -59,19 +81,7 @@ static inline QSGNode* qskUpdateGraphicNode( if ( control->testUpdateFlag( QskControl::PreferRasterForTextures ) ) mode = QskTextureRenderer::Raster; - /* - Aligning the rect according to scene coordinates, so that - we don't run into rounding issues downstream, where values - will be floored/ceiled ending up with a slightly different - aspect ratio. - */ - QRectF r( - control->mapToScene( rect.topLeft() ), - rect.size() * control->window()->effectiveDevicePixelRatio() ); - - r = qskInnerRect( r ); - r.moveTopLeft( control->mapFromScene( r.topLeft() ) ); - + const auto r = qskSceneAlignedRect( control, rect ); graphicNode->setGraphic( control->window(), graphic, colorFilter, mode, r, mirrored ); @@ -161,20 +171,7 @@ static inline QSGNode* qskUpdateArcNode( if ( arcNode == nullptr ) arcNode = new QskArcNode(); - auto r = rect; -#if 1 - { - /* - Fiddling around with the pixel ratio should be hidden below QskArcNode. - Code will break once QskArcNode is not texture based anymore. TODO ... - */ - - const auto ratio = control->window()->effectiveDevicePixelRatio(); - absoluteMetrics.setWidth( absoluteMetrics.width() * ratio ); - r.setSize( r.size() * ratio ); - } -#endif - + const auto r = qskSceneAlignedRect( control, rect ); arcNode->setArcData( r, absoluteMetrics, fillGradient, control->window() ); return arcNode; diff --git a/src/graphic/QskGraphicTextureFactory.cpp b/src/graphic/QskGraphicTextureFactory.cpp index 0a4548a9..3a256448 100644 --- a/src/graphic/QskGraphicTextureFactory.cpp +++ b/src/graphic/QskGraphicTextureFactory.cpp @@ -60,7 +60,7 @@ QSGTexture* QskGraphicTextureFactory::createTexture( QQuickWindow* window ) cons using namespace QskTextureRenderer; const uint textureId = createTextureFromGraphic( - QskTextureRenderer::OpenGL, m_size, m_graphic, m_colorFilter, + window, QskTextureRenderer::OpenGL, m_size, m_graphic, m_colorFilter, Qt::IgnoreAspectRatio ); return textureFromId( window, textureId, m_size ); diff --git a/src/nodes/QskGraphicNode.cpp b/src/nodes/QskGraphicNode.cpp index dfb0c325..4c0b9943 100644 --- a/src/nodes/QskGraphicNode.cpp +++ b/src/nodes/QskGraphicNode.cpp @@ -78,7 +78,7 @@ void QskGraphicNode::setGraphic( if ( isTextureDirty ) { textureId = QskTextureRenderer::createTextureFromGraphic( - renderMode, textureSize, graphic, colorFilter, Qt::IgnoreAspectRatio ); + window, renderMode, textureSize, graphic, colorFilter, Qt::IgnoreAspectRatio ); } QskTextureNode::setTexture( window, rect, textureId, mirrored ); diff --git a/src/nodes/QskPaintedNode.cpp b/src/nodes/QskPaintedNode.cpp index 2f029ded..574cae82 100644 --- a/src/nodes/QskPaintedNode.cpp +++ b/src/nodes/QskPaintedNode.cpp @@ -56,7 +56,7 @@ void QskPaintedNode::update( QQuickWindow* window, { PaintHelper helper( this ); textureId = QskTextureRenderer::createTexture( - renderMode, rect.size(), &helper ); + window, renderMode, rect.size(), &helper ); } QskTextureNode::setTexture( window, rect, textureId ); diff --git a/src/nodes/QskTextureNode.cpp b/src/nodes/QskTextureNode.cpp index 8e137cf3..ae90fd66 100644 --- a/src/nodes/QskTextureNode.cpp +++ b/src/nodes/QskTextureNode.cpp @@ -1,5 +1,5 @@ #include "QskTextureNode.h" -#include "QskTextureRenderer.h" +#include "QskFunctions.h" #include #include @@ -237,7 +237,7 @@ class QskTextureNodePrivate final : public QSGGeometryNodePrivate void setTextureId( QQuickWindow*, uint id ); - void updateTextureGeometry( const QQuickWindow* window ) + void updateTextureGeometry() { QRectF r( 0, 0, 1, 1 ); @@ -253,15 +253,7 @@ class QskTextureNodePrivate final : public QSGGeometryNodePrivate r.setBottom( 0 ); } - const qreal ratio = window->effectiveDevicePixelRatio(); - - const qreal x = int( rect.x() / ratio ) * ratio; - const qreal y = int( rect.y() / ratio ) * ratio; - const qreal w = rect.width() / ratio; - const qreal h = rect.height() / ratio; - - QSGGeometry::updateTexturedRectGeometry( - &geometry, QRectF( x, y, w, h ), r ); + QSGGeometry::updateTexturedRectGeometry( &geometry, rect, r ); } QSGGeometry geometry; @@ -301,7 +293,7 @@ void QskTextureNode::setTexture( QQuickWindow* window, d->rect = rect; d->mirrored = mirrored; - d->updateTextureGeometry( window ); + d->updateTextureGeometry(); markDirty( DirtyGeometry ); } diff --git a/src/nodes/QskTextureRenderer.cpp b/src/nodes/QskTextureRenderer.cpp index d85328fe..f7901ffe 100644 --- a/src/nodes/QskTextureRenderer.cpp +++ b/src/nodes/QskTextureRenderer.cpp @@ -25,11 +25,13 @@ #include #endif -static uint qskCreateTextureOpenGL( +static uint qskCreateTextureOpenGL( QQuickWindow* window, const QSize& size, QskTextureRenderer::PaintHelper* helper ) { - const int width = size.width(); - const int height = size.height(); + const auto ratio = window ? window->effectiveDevicePixelRatio() : 1.0; + + const int width = ratio * size.width(); + const int height = ratio * size.height(); QOpenGLFramebufferObjectFormat format1; format1.setAttachment( QOpenGLFramebufferObject::CombinedDepthStencil ); @@ -44,6 +46,7 @@ static uint qskCreateTextureOpenGL( { QPainter painter( &pd ); + painter.scale( ratio, ratio ); painter.setCompositionMode( QPainter::CompositionMode_Source ); painter.fillRect( 0, 0, width, height, Qt::transparent ); @@ -77,15 +80,26 @@ static uint qskCreateTextureOpenGL( return fbo.takeTexture(); } -static uint qskCreateTextureRaster( +static uint qskCreateTextureRaster( QQuickWindow* window, const QSize& size, QskTextureRenderer::PaintHelper* helper ) { - QImage image( size, QImage::Format_RGBA8888_Premultiplied ); + const auto ratio = window ? window->effectiveDevicePixelRatio() : 1.0; + + QImage image( size * ratio, QImage::Format_RGBA8888_Premultiplied ); image.fill( Qt::transparent ); { QPainter painter( &image ); + + /* + setting a devicePixelRatio for the image only works for + value >= 1.0. So we have to scale manually. + */ + painter.scale( ratio, ratio ); + helper->paint( &painter, size ); + + image.save( "/tmp/xx.png" ); } const auto target = QOpenGLTexture::Target2D; @@ -165,7 +179,8 @@ QskTextureRenderer::PaintHelper::~PaintHelper() } uint QskTextureRenderer::createTexture( - RenderMode renderMode, const QSize& size, PaintHelper* helper ) + QQuickWindow* window, RenderMode renderMode, + const QSize& size, PaintHelper* helper ) { #if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) // Qt6.0.0 is buggy when using FBOs. So let's disable it for the moment TODO ... @@ -180,13 +195,13 @@ uint QskTextureRenderer::createTexture( } if ( renderMode == Raster ) - return qskCreateTextureRaster( size, helper ); + return qskCreateTextureRaster( window, size, helper ); else - return qskCreateTextureOpenGL( size, helper ); + return qskCreateTextureOpenGL( window, size, helper ); } uint QskTextureRenderer::createTextureFromGraphic( - RenderMode renderMode, const QSize& size, + QQuickWindow* window, RenderMode renderMode, const QSize& size, const QskGraphic& graphic, const QskColorFilter& colorFilter, Qt::AspectRatioMode aspectRatioMode ) { @@ -214,5 +229,5 @@ uint QskTextureRenderer::createTextureFromGraphic( }; PaintHelper helper( graphic, colorFilter, aspectRatioMode ); - return createTexture( renderMode, size, &helper ); + return createTexture( window, renderMode, size, &helper ); } diff --git a/src/nodes/QskTextureRenderer.h b/src/nodes/QskTextureRenderer.h index 7366bd07..b69a3517 100644 --- a/src/nodes/QskTextureRenderer.h +++ b/src/nodes/QskTextureRenderer.h @@ -42,10 +42,11 @@ namespace QskTextureRenderer virtual void paint( QPainter*, const QSize& ) = 0; }; - QSK_EXPORT uint createTexture( RenderMode, const QSize&, PaintHelper* ); + QSK_EXPORT uint createTexture( + QQuickWindow*, RenderMode, const QSize&, PaintHelper* ); QSK_EXPORT uint createTextureFromGraphic( - RenderMode, const QSize&, const QskGraphic&, + QQuickWindow*, RenderMode, const QSize&, const QskGraphic&, const QskColorFilter&, Qt::AspectRatioMode ); QSK_EXPORT QSGTexture* textureFromId(