ebiten: Fullscreen broken on X11 with HiDPI
Repro:
- Set display DPI to something other than 96:
echo Xft.dpi: 144 | xrdb -merge
- Run
examples/windowsize
- Press
F
Observe that a large part of the screen is cut off (see screenshots).
Note how Xft.dpi
does not influence the Device Scale Factor, but it does change the initial window size and causes this weird fullscreen scale up.
Reproduced on:
- X11/i3
- Wayland/Sway/Xwayland
Does NOT reproduce on:
- Cinnamon
Most likely because ebiten has its own support for querying device scale that is specific to Cinnamon and GNOME, while not supporting anything else; at the same time, glfw has its different support and these two disagree.
Maybe we should just always use glfw’s content scale?
Note though:
// deviceScaleFactor() is a scale by desktop environment (e.g., Cinnamon), while GetContentScale() is X's scale.
I do not quite understand this - when do these two ever differ, except when there simply is no desktop environment managing this at all? In fact, do we ever handle the case of these two differing right?
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 45 (45 by maintainers)
Commits related to this issue
- Replace Ebiten by an experimental build with https://github.com/hajimehoshi/ebiten/issues/1774 fixed. — committed to divVerent/aaaaxy by divVerent 3 years ago
- Split the concept of device scale and screen scale. We now set deviceScale to always the mapping from logical window system pixels to device independent pixels (which is what Ebiten API users expect)... — committed to divVerent/ebiten by divVerent 3 years ago
- Split the concept of device scale and screen scale. We now set deviceScale to always the mapping from logical window system pixels to device independent pixels (which is what Ebiten API users expect)... — committed to divVerent/ebiten by divVerent 3 years ago
- Split the concept of device scale and screen scale. We now set deviceScale to always the mapping from logical window system pixels to device independent pixels (which is what Ebiten API users expect)... — committed to divVerent/ebiten by divVerent 3 years ago
- Split the concept of device scale and screen scale. We now set deviceScale to always the mapping from logical window system pixels to device independent pixels (which is what Ebiten API users expect)... — committed to divVerent/ebiten by divVerent 3 years ago
- Split the concept of device scale and screen scale. We now set deviceScale to always the mapping from logical window system pixels to device independent pixels (which is what Ebiten API users expect)... — committed to divVerent/ebiten by divVerent 3 years ago
- Split the concept of device scale and screen scale. We now set deviceScale to always the mapping from logical window system pixels to device independent pixels (which is what Ebiten API users expect)... — committed to divVerent/ebiten by divVerent 3 years ago
- Split the concept of device scale and screen scale. We now set deviceScale to always the mapping from logical window system pixels to device independent pixels (which is what Ebiten API users expect)... — committed to divVerent/ebiten by divVerent 3 years ago
- Split the concept of device scale and screen scale. We now set deviceScale to always the mapping from logical window system pixels to device independent pixels (which is what Ebiten API users expect)... — committed to divVerent/ebiten by divVerent 3 years ago
- Split the concept of device scale and screen scale. We now set deviceScale to always the mapping from logical window system pixels to device independent pixels (which is what Ebiten API users expect)... — committed to divVerent/ebiten by divVerent 3 years ago
- Split the concept of device scale and screen scale. We now set deviceScale to always the mapping from logical window system pixels to device independent pixels (which is what Ebiten API users expect)... — committed to divVerent/ebiten by divVerent 3 years ago
- Split the concept of device scale and screen scale. We now set deviceScale to always the mapping from logical window system pixels to device independent pixels (which is what Ebiten API users expect)... — committed to divVerent/ebiten by divVerent 3 years ago
- Split the concept of device scale and screen scale. We now set deviceScale to always the mapping from logical window system pixels to device independent pixels (which is what Ebiten API users expect)... — committed to divVerent/ebiten by divVerent 3 years ago
- Switch out the devicescale implementation by one that relies on glfw/xrandr. (#1800) This should fix fullscreen mode on Linux/X11 systems in general, while not affecting other systems. Note that ... — committed to hajimehoshi/ebiten by divVerent 3 years ago
- Split the concept of device scale and screen scale. We now set deviceScale to always the mapping from logical window system pixels to device independent pixels (which is what Ebiten API users expect)... — committed to divVerent/ebiten by divVerent 3 years ago
- Move VideoModeScaleAt into internal/uidriver/glfw. (#1812) It's only used by GLFW, and has been in devicescale only to ease migration to separate video mode vs content scaling. Updates #1774 — committed to hajimehoshi/ebiten by divVerent 3 years ago
I’m rather confident about correctness for Windows now.
Relevant deltas for Windows:
dpiAware
manifest setting so my binary is probably not affected by this.Relevant deltas for OS X:
Filed these GLFW bugs:
Note that a fix to any of these might need an Ebiten update in response. As Ebiten’s go.mod controls the GLFW version used, this can then be in sync.
For now, I figured out that querying the workarea only sometimes works (namely, when the desktop environment is setting one), so I am now switching to an approach that doesn’t use the workarea query but really operates at XRandR level.
Sounds good, will try.
The main complication will be that I can’t use the devicescale mode or it’d cause a cyclic dependency. I’ll probably at least at first just skip that module entirely for the GLFW/X11 code path.
The other complication is that there’s no “explicitly intended” way to get the scale from XRandR - one can get a matrix, or the current mode and the current output size. I think I’ll go for the latter and just divide. Have to see though how that interacts with panning (which one can set up too in XRandR).
On Sat, Aug 28, 2021 at 8:16 AM Hajime Hoshi @.***> wrote:
Okay, so from what I see I guess the first thing to decide is, what should Ebiten’s device scale factor be?
It seems like Ebiten primarily uses it to map from game-defined to actual window sizes, but also - sadly - in lots of other places.
So my very first question would be: why? Can’t this be simplified and deviceScaleFactor be used way less?
Then there is GLFW’s own content scale. This is entirely unnecessary but “nice to have”.
What I would suggest as correct behavior:
This way should work perfectly on X11. Can’t tell it will work this way on Windows or Mac - depends on what kind of coordinates GLFW returns on these platforms.
Making everything work seems almost possible:
Catch is, if we call GetSize too early, we will stay at the wrong size - and I believe this happened to me once, although I cannot repro. Would it actually be OK to just call GetSize every frame, or is that call expensive?
What this can NOT fix (which is why this is just an “almost”) is predicting the screen size BEFORE entering fullscreen. This is plain impossible using GLFW’s API. I guess the way to fix this is filing a GLFW feature request to either return “adjusted for scale” resolutions, or to include the scale factor as an additional struct member in the monitor info.
Impact of this breakage to many games would be displaying the wrong fullscreen size in the graphics settings menu, but everything else would work.
Impact of this breakage to my game in specific would be that I will calculate a too large initial window size in windowed mode on such systems. Luckily it appears that the desktop environments clip this overly large size to the screen size then, so this is kinda OK (plus I provide a setting for window size anyway).
On Sat, Aug 21, 2021, 02:48 Hoshi, Hajime (星一) @.***> wrote:
Trying to use other conversions as a “proxy” to find a chain that should be the identity.
This suggests that the combination of all these conversions should always be the identity.
Thus,
fromGLFWMonitorPixel . (* deviceScaleFactor) . (/ screenScale) . (* screenScale)
must be the identity, so fromGLFWMonitorPixel can always just divide by deviceScaleFactor (which is what it indeed does).Let’s see if I can find more such relations to solve this.