https://bugs.documentfoundation.org/show_bug.cgi?id=172896
Bug ID: 172896
Summary: Qt/KF Wayland: fractional display scaling is rounded
up to the next integer scale, so the UI is sized and
rendered wrong
Product: LibreOffice
Version: 26.2.4.2 release
Hardware: All
OS: Linux (All)
Status: UNCONFIRMED
Severity: normal
Priority: medium
Component: UI
Assignee: [email protected]
Reporter: [email protected]
Description:
Environment: Wayland session (tested on KDE Plasma/KWin), Qt6 + kf6 VCL
backend, with a fractional display scale set in the compositor (e.g. 125%,
150%, 220%).
On Wayland, wl_output can only advertise an integer buffer scale, so a
fractionally scaled output reports a rounded-up integer - 2 for 125%, 3 for
220%. VCL derives its DPI from QScreen::devicePixelRatio(), which returns that
integer, so the UI is laid out for the wrong scale (e.g. toolbars at 200% on a
125% display).
This was previously worked around by forcing the Qt
HighDpiScaleFactorRoundingPolicy to Round (tdf#159915). That avoids the
wrong-size layout, but forces integer buffer scaling: each surface is rendered
at the next whole ratio and downscaled by the compositor (~1.86x pixel overdraw
at 220%), wasting GPU and softening the output.
The true fractional scale is available up front from the protocol: wl_output's
current mode (device pixels) divided by the logical size Qt reports as
QScreen::geometry() gives the real scale (1.25, 2.2, ...), no surface required.
Using that for both the layout DPI and the frame's device-pixel-ratio lets Qt
6's default PassThrough policy render at the exact output scale - correctly
sized and with no overdraw.
Related: tdf#159915 (the Round-policy workaround this replaces).
Steps to Reproduce:
1. Wayland session, set a fractional display scale (e.g. 125%).
2. Open LibreOffice with the qt6/kf6 VCL plugin.
3. Toolbar/UI is sized as if ~200% (see "before" screenshots).
Actual Results:
The UI is laid out for the wrong scale. At a 125% display scale the toolbar
items are rendered as if ~200% were set - much larger than the configured
scale. The cause is that VCL uses the integer scale wl_output advertises (2 at
125%, 3 at 220%) instead of the real fractional scale, so the whole UI is
oversized. Conversely, when the HighDpiScaleFactorRoundingPolicy is forced to
Round the size is correct but every surface is rendered at the next integer
scale and downscaled by the compositor (~1.86x pixel overdraw at 220%), which
wastes GPU and softens the output.
Expected Results:
The UI should be sized to match the configured fractional display scale (125%
-> 125%, 220% -> 220%), and rendered at that exact scale, without the
compositor having to downscale an oversized buffer.
Reproducible: Always
User Profile Reset: No
Additional Info:
Environment: Wayland session (tested on KDE Plasma/KWin), Qt6 + kf6 VCL
backend, with a fractional display scale set in the compositor.
Root cause: wl_output can only advertise an integer buffer scale, so a
fractionally scaled output reports a rounded-up integer (2 for 125%, 3 for
220%). VCL derives both its DPI and the frame's device-pixel-ratio from
QScreen::devicePixelRatio(), which returns that integer, so the UI is laid out
and rendered for the wrong scale.
Fix: read the real fractional scale up front from the protocol - wl_output's
current mode (device pixels) divided by the logical size Qt reports as
QScreen::geometry() - and use it for both the layout DPI and the frame's
devicePixelRatioF() so they agree. With that, Qt 6's default PassThrough policy
renders at the exact output scale with no overdraw. A patch is up for review on
Gerrit (change 208347).
Related: tdf#159915 (the forced-Round workaround this replaces).
Before/after screenshots at 125% (and 220%) attached.
--
You are receiving this mail because:
You are the assignee for the bug.