Wayland's fractional scale and Fedora
Jonas Ådahl
jadahl at redhat.com
Fri May 17 15:19:09 UTC 2024
On Thu, May 16, 2024 at 03:34:51PM +0400, Maxim Kartashev wrote:
> Fedora 40 is a major Linux distro that supports Wayland's
> fractional-scale-v1 protocol
> (https://wayland.app/protocols/fractional-scale-v1), so I decided to
> base my experiments with the true fractional scaling support for this
> Wakefield project on such a system. In parenthesis, I was a bit
> surprised that in order to be able to actually specify non-integer
> scale, one has to execute a command in a terminal (gsettings set
> org.gnome.mutter experimental-features
> "['scale-monitor-framebuffer']"). Perhaps, it is a work in progress
> affair?
>
> After having implemented all the necessary protocols on the JDK side
> (fractional-scale-v1, viewporter), the results were quite unexpected.
> Instead of getting a sharper image at, say, 150%, the overall quality
> seemed more blurry than before. Looking at screenshots at 2-3x, this
> has become even more apparent. So for the moment I'm putting
> fractional scaling support on hold and will only implement the basis
> for it, i.e. the viewporter protocol.
>
> Some data to better illustrate my expectation considering the same
> 150% scaling: currently the scale reported by the server to us will be
> 2x or 200%. So for a Swing window of 300x300 units we create a backing
> buffer of 600x600 pixels and this buffer is then shared with the
> Wayland server. The server (compositor) then must shrink it to 450x450
> pixels before sending it to the screen to comply with 150% scaling.
> Shrinking 600 pixels to 450 pixels may make the resulting picture
> somewhat blurry, but probably not significantly more blurry. After
> all, this transformation does not have to pull pixels out of thin air
> unlike the opposite when an image is made larger than the original.
>
> By employing the viewporter protocol and upon learning the actual
> window scale from fractional-scale-v1, we create the backing buffer of
> only 450x450 pixels now. And it seems that the job of the compositor
> is way simpler now - the final transformation is that of identity,
> i.e. a buffer pixel corresponds to a screen pixel 1:1.
>
> I don't really understand how to experimentally verify that; the best
> I could think of is to take a screenshot and look at it at 100% scale.
> To my surprise, the screenshot size was 600x600. This may explain the
> blurriness: if the compositor had to upscale the image to the closest
> larger integer scale and then scale it back again by the factor of
> 0.75, the result could be expected to be more blurry. But this may
> just be an artifact of screenshotting.
>
> I wonder if our RedHat colleagues can provide any commentary?
When using fractional scaling, there are three things that needs to happen
in the compositor for the client provided buffer content to be as crisp
as possible, and that is 1) the position the texture is painted at needs
to be aligned with the physical pixel grid, and not the logical one, and
2) the width of the painted texture needs to align with the physical
pixel grid, and not the logical one, and 3) the painted texture width
needs to perfectly match width the client buffer.
1 should already be handled in mutter, and 2 and 3 isn't properly yet.
Some days ago I posted a patch[1] that attempts to resolve that.
Client side, there are also some things to take into consideration.
First is that the scale you receive are not necessarily 1.5 or 1.75, but
a fractional value close to it. The fraction is calculated in a way to
be "close enough" to a relatable number (e.g. 1.5), but still result in
a integer logical monitor width multiplied with the scale exactly
resulting in the monitor mode of that monitor.
Second is that some fractional scales mean you get "half" pixels wide
buffers. When you get this, there is an intended way to round this
number to an actual width, but you need to take the rounding into
consideration in your rendering.
E.g. if you have a 101 wide window, a 1.5 scale factor, the perfect size
is 151.5, which IIRC is then rounded to 152. If you then render your
content with 1.5, it will not match up perfectly according to
expectations, and you'll get blurry result.
When drawing *almost* correct, you tend to get worse result than drawing
much larger, scaling down, which is probably why it became worse when
you turned fractional scaling on. Whether it was a compositor side
issue, or a client side, or both, needs verification.
To verify, I suggest dumping the contents of your passed buffer, and
taking a screenshot of the monitor in question (Prnt-Screen -> Screen),
then comparing by zooming in a lot with an image viewer that supports
nearest neighbour scaling.
>
> P.S. Cursors in gnome applications are still scaled using the "old"
> buffer scaling technique that only supports integer scale and do not
> employ viewporter. Also work in progress?
>
There is a bug and an intention to fix using wp_viewporter with cursor
surfaces, here: https://gitlab.gnome.org/GNOME/mutter/-/issues/2633
Hope this helps.
Jonas
[1] https://gitlab.gnome.org/GNOME/mutter/-/issues/3346#note_2111091
More information about the wakefield-dev
mailing list