Calculate correct device pixel ratio when rendering to layer

When rendering to a layered item, the actual device pixel ratio
is determined by the ratio between the width of the texture and
the width of the logical rect.

For most use cases, using the window's device pixel ratio would
be correct, since the texture size is automatically calculated
based on this. But in the cases where a manual texture size is
set it would be incorrect and this would cause artifacts in
the antialiasing for text and shapes.

This also adds the correct scale factor to shapes, since this
was even missing the device pixel ratio factor.

Fixes: QTBUG-139997
Change-Id: Ibf1392f546f5cbcedd062852cbd87c0c0c097460
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2025-09-09 12:31:03 +02:00
parent e0fdb3626a
commit c1e0c1a5ca
4 changed files with 141 additions and 2 deletions

View File

@ -115,7 +115,7 @@ namespace {
memcpy(buf->data() + offset + viewIndex * 64, m.constData(), 64);
}
matrixScale = qSqrt(qAbs(state.determinant()));
matrixScale = qSqrt(qAbs(state.determinant())) * state.devicePixelRatio();
memcpy(buf->data() + offset + newEffect->viewCount() * 64, &matrixScale, 4);
changed = true;

View File

@ -407,7 +407,18 @@ void QSGRhiLayer::grab()
// layer contents do not change.
m_dirtyTexture = false;
m_renderer->setDevicePixelRatio(m_dpr);
// The texture is essentially a virtual screen with a dpr == m_pixelSize / m_logicalRect
// For automatic texture sizes this factor will be equal to m_dpr.
// If the texture size is manually set, we need to know the actual ratio. This only
// works correctly for uniform rects, but this is already the prerequisite everywhere this
// factor is used.
if (m_logicalRect.isValid() && !m_pixelSize.isNull()) {
qreal actualDpr = std::max(m_pixelSize.width() / m_logicalRect.width(),
m_pixelSize.height() / m_logicalRect.height());
m_renderer->setDevicePixelRatio(actualDpr);
} else {
m_renderer->setDevicePixelRatio(m_dpr);
}
m_renderer->setDeviceRect(m_pixelSize);
m_renderer->setViewportRect(m_pixelSize);

View File

@ -0,0 +1,93 @@
import QtQuick
import QtQuick.Shapes
Item {
width: 820
height: 850
Item {
x: 160
y: 160
implicitWidth: 100
implicitHeight: 100
scale: 5
Item {
implicitWidth: 100
implicitHeight: 100
Shape {
implicitWidth: 80
implicitHeight: 80
preferredRendererType: Shape.CurveRenderer
ShapePath {
strokeColor: "transparent"
fillColor: "red"
fillRule: ShapePath.WindingFill
PathSvg { path: "M 10 35 C 10 23.9543 18.9543 15 30 15 C 41.0457 15 50 23.9543 50 35 C 50 23.9543 58.9543 15 70 15 C 81.0457 15 90 23.9543 90 35 C 90 55 76.6667 75 50 95 C 23.3333 75 10 55 10 35 " }
}
}
}
Item {
x: 80
implicitWidth: 100
implicitHeight: 100
layer.enabled: true
layer.textureSize: Qt.size(500, 500)
Shape {
implicitWidth: 80
implicitHeight: 80
preferredRendererType: Shape.CurveRenderer
ShapePath {
strokeColor: "transparent"
fillColor: "red"
fillRule: ShapePath.WindingFill
PathSvg { path: "M 10 35 C 10 23.9543 18.9543 15 30 15 C 41.0457 15 50 23.9543 50 35 C 50 23.9543 58.9543 15 70 15 C 81.0457 15 90 23.9543 90 35 C 90 55 76.6667 75 50 95 C 23.3333 75 10 55 10 35 " }
}
}
}
Item {
y: 80
implicitWidth: 100
implicitHeight: 100
Shape {
implicitWidth: 80
implicitHeight: 80
preferredRendererType: Shape.CurveRenderer
ShapePath {
strokeColor: "red"
fillRule: ShapePath.WindingFill
PathSvg { path: "M 10 35 C 10 23.9543 18.9543 15 30 15 C 41.0457 15 50 23.9543 50 35 C 50 23.9543 58.9543 15 70 15 C 81.0457 15 90 23.9543 90 35 C 90 55 76.6667 75 50 95 C 23.3333 75 10 55 10 35 " }
}
}
}
Item {
y: 80
x: 80
implicitWidth: 100
implicitHeight: 100
layer.enabled: true
layer.textureSize: Qt.size(500, 500)
Shape {
implicitWidth: 80
implicitHeight: 80
preferredRendererType: Shape.CurveRenderer
ShapePath {
strokeColor: "red"
fillRule: ShapePath.WindingFill
PathSvg { path: "M 10 35 C 10 23.9543 18.9543 15 30 15 C 41.0457 15 50 23.9543 50 35 C 50 23.9543 58.9543 15 70 15 C 81.0457 15 90 23.9543 90 35 C 90 55 76.6667 75 50 95 C 23.3333 75 10 55 10 35 " }
}
}
}
}
}

View File

@ -0,0 +1,35 @@
import QtQuick
Item {
width: 200
height: 110
Item {
implicitWidth: 100
implicitHeight: 100
scale: 10
Item {
implicitWidth: 100
implicitHeight: 100
Text {
text: "f"
anchors.centerIn: parent
}
}
Item {
x: 10
implicitWidth: 100
implicitHeight: 100
layer.enabled: true
layer.textureSize: Qt.size(1000, 1000)
Text {
text: "f"
anchors.centerIn: parent
}
}
}
}