godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
86.82k stars 19.43k forks source link

Allow Hidpi leads to wrong window scale #42085

Open okapii opened 3 years ago

okapii commented 3 years ago

Godot version: 3.2.3 RC 6 Official, MacOS

OS/device including version:

Issue description: Checking "Allow Hidpi" in the project settings (Display > Window > Dpi) scales down the window size to half (?) its intended size. It happens with newly created vanilla 3D-projects, too. So this seems not to be about some other conflicting setting. This appears to be a regression as the current stable build does not have this problem. It has been around for a number of release candidates already.

Steps to reproduce: Check "Allow Hidpi" in project settings (Display > Window > Dpi).

Minimal reproduction project: Happy to provide the fresh test-project I just created but since this is a one click operation for a newly created project, I refrained from uploading anything at this point for now.

Calinou commented 3 years ago

Can you reproduce this in older 3.2.3 RCs and betas? You can download them here.

okapii commented 3 years ago

Just checked RC1. The issue was in that one already.

Calinou commented 3 years ago

@okapii Thanks! If you can build Godot from source, can you bisect the regression? For the bisection, the "good" commit to use is 3.2.2-stable and the bad commit is a24e30abd7b1bc226dc1231ef2b8eb5a9ee50df6.

I don't have a macOS machine with an hiDPI display to test here.

okapii commented 3 years ago

Sorry, not really equipped with infrastructure / knowledge on how to do that … :( Could try finding the time to figure this out next weekend.

okapii commented 3 years ago

I just updated to the new Godot 3.2.3 and the issue exists in that one, too.

pk-nb commented 3 years ago

Hi there! I ran into this issue as well after updating a basic project to 3.2.3 and bisected the two commits above. I believe I've found the specific change:

commit e9ab41b71d59f5555d1171c75b2aa5a72b6e801b
Author: bruvzg <7645683+bruvzg@users.noreply.github.com>
Date:   Tue Jul 7 21:37:05 2020 +0300

    [macOS, 3.2] Implement seamless display scaling.

 core/bind/core_bind.cpp    |  10 ++++
 core/bind/core_bind.h      |   2 +
 core/os/os.h               |   2 +
 doc/classes/OS.xml         |  20 +++++++
 editor/editor_node.cpp     |   4 ++
 editor/editor_run.cpp      |  29 ++++++----
 editor/project_manager.cpp |   7 ++-
 platform/osx/os_osx.h      |  12 +---
 platform/osx/os_osx.mm     | 138 ++++++++++++++++++++++++++-------------------
 9 files changed, 143 insertions(+), 81 deletions(-)

Specific commit: https://github.com/godotengine/godot/commit/e9ab41b71d59f5555d1171c75b2aa5a72b6e801b

While I am new to the codebase, I would suspect the code change in editor/editor_run.cpp for window size and scale is what causes this. Not sure if intentional, but does seem surprising to see a halved window size (actual pixels) compared to points that match the rest of the OS windowing.

(Aside: It does appear to properly fix window position centering on a dual monitor setup when starting up the game compared to 3.2.2 which is great!)

Calinou commented 3 years ago

cc @bruvzg

bruvzg commented 3 years ago

What's "wrong window scale"? When hiDPI is enabled real screen resolution is used and the window with the same pixel size will appear smaller, it's done for handling multiple displays with different DPI.

Before #40201 scaled resolution was used for both hiDPI and loDPI and multi monitor setups were completely unusable.

For example if you have 1024x768 window in loDPI mode, Godot will create and render 1024x768 window and OS will upscale it to double size on retina screen and keep as is on normal screen. In hiDPI mode OS will downscale it on normal screen and keep as is on retina.

pk-nb commented 3 years ago

Hey @bruvzg, thanks for the response. The sizing behavior seems to be much improved! Hoping to check my understanding now the behavior has changed a bit. Are the following statements correct?

The only thing I'm worried about this change is that I'd like to use `Allow HiDPI = true" (for better font oversampling/rasterization) yet have a predictable window size. That seems impossible to do as we can't assume the device density (could be 1x, 2x, 3x, etc) but Test Width and Test Height are interpreted in pixels (effectively baking in a single density assumption).

If my understanding is correct, could I suggest the following?

My feeling is that this would be more intuitive as it more closely matches how macOS handles window units. It seems it would make it easier for developers to setup the same window sizing across monitors in hiDPI mode too, without resorting to scripting.

I am new to this and there may be other solutions or thinking I'm unaware of—so forgive me if this suggestion seems like a bad idea. Thanks so much for your thoughts!


(aside, wanted to share the current behavior for reference)

Example of behavior in 3.2.3 for reference

Screenshots of a game with a native size of 480x270 on a HiDPI screen.

Starting window size when "Allow HiDPI = false" Window is 480x270 points (960x540 pixels on my HiDPI display). Screen Shot 2020-09-20 at 2 51 49 PM
Starting window size when "Allow HiDPI = true" Window is 240x135 points (480x270 pixels on my HiDPI display). Screen Shot 2020-09-20 at 2 51 36 PM
bruvzg commented 3 years ago

Godot do not have any dynamic UI scaling support (#21446) and all window management is designed to use pixels, so it's always using pixels, we can't use points unless DPI independent rendering is implemented in the renderer. In loDPI mode it's still using pixels but reports to OS that it does not support hiDPI.

Current solution was done to make editor usable on dual hiDPI + loDPI monitor setup (which is probably the most common mac setup, retina MacBook + external display). I agree, this approach is not most intuitive for macOS users, but it's consistent with other OSes. And 3.2.2 behavior was my previous attempt to solve the issue (which was faulty, because I was implementing it without hiDPI monitor to test).

Using points is the best solution, but it will require much bigger changes to the renderer to make everything function properly (and outside of mine expertise). And it's also the way to go on Windows 10, some Linux DEs (AFAIK only latest version of GNOME) seems to have DPI independent mode, but I'm sure how exactly it's implemented.

Calinou commented 3 years ago

some Linux DEs (AFAIK only latest version of GNOME) seems to have DPI independent mode, but I'm sure how exactly it's implemented.

As far as I know, loDPI fallbacks on Linux are only available in some Wayland-based desktop environments, not X11. This is because X11 is too limited to provide proper mouse input for windows scaled by the display server.

DoctorWhoof commented 3 years ago

For what it's worth, I like the current behavior in 3.2.3, i.e. turning on HiDPI causes the window to be smaller, since it's displaying the true size in pixels.

This allows me the design a UI with hiDPI that looks identical, albeit smaller, to its non-hiDPI counterpart until I maximize it or go full screen.

What the OP is asking actually makes sense and is more in line with Apple's Retina screen guidelines (I think), but I find less practical. Maybe both can be an option?

Now if Godot's controls had automatic dynamic resizing that preserved the apparent size of everything when changing pixel density, then yes, I think it would make a lot more sense to preserve the dimensions in relation to the monitor size, not in pixels, but with higher/lower pixel count. Is there a request for that already?

Calinou commented 3 years ago

@DoctorWhoof We would really prefer to encourage best practices out of the box. Supporting hiDPI displays correctly is a best practice :slightly_smiling_face:

Gotta get those WSGF labels somehow…

Now if Godot's controls had automatic dynamic resizing that preserved the apparent size of everything when changing pixel density, then yes, I think it would make a lot more sense to preserve the dimensions in relation to the monitor size, not in pixels, but with higher/lower pixel count. Is there a request for that already?

This already exists in the form of the 2d stretch mode. See Multiple resolutions in the documentation. As for applying a manual scale factor on top of that (or independently of the 2d stretch mode), see https://github.com/godotengine/godot/pull/21446.

DoctorWhoof commented 3 years ago

This already exists in the form of the 2d stretch mode

That works well for games, not for applications, which is what I'm focusing on now. For instance, when using 2D stretch mode all text is resized when resizing the window, which is not what you want in an application. Just resize Godot itself to see what I mean.

I feel that to satisfy the original request with Godot applications, Godot's Controls would need to behave in a resolution independent way - i.e. not use pixels as the unit, so that layout can be preserved while increasing pixel density. The effect can actually be achieved via code (I have it working, including resizing the UI on the fly with "zoom" controls), but implementing it is a pain, especially if you didn't start the project like that from the get go.

Supporting hiDPI displays correctly is a best practice

I strongly feel that to support HiDPI switching correctly with applications Godot would need resolution independent controls for GUIs, which is probably a full redesign not in the horizon (unless I'm mistaken!). In the absence of that, the way it handles hiDPI switching now is Ok for applications (layout is preserved, despite the size change), bad for games (window size relative to display size changes, as described in the original request).

Thanks!

Calinou commented 3 years ago

@DoctorWhoof As I said, we need to expose a way to manually change the scale factor independently of the window size. This is what https://github.com/godotengine/godot/pull/21446 provides.

The editor is already designed in DPI-indepedent pixels for the most part, although it's a manual process – all values have to be multiplied by the EDSCALE macro.

DoctorWhoof commented 3 years ago

Yes @Calinou! Sorry I missed that point, I believe proper hiDPI (like the original request) + a global scale factor like that would work for applications.

Thanks!

okapii commented 3 years ago

Has there been made any progress regarding this issue? I am pretty much stuck on 3.2.2 for utilising 2D-nodes in my 3D game for the GUI which are all displayed substantially too small in newer versions because of how things are handled now. This seems like a fairly common combination so I would assume that I am probably not the only one having trouble here?

Calinou commented 3 years ago

Has there been made any progress regarding this issue?

Use the 2d stretch mode and expand stretch aspect to ensure that 2D elements are readable on any screen resolution. See Multiple resolutions in the documentation for more information.

For games, the 2d (or viewport) stretch mode are almost always what you want. Pretty much all games released since the late 90s use a variant of this stretch mode. disabled should be reserved to non-game applications.

You can check the godot-demo-projects repository for examples of projects that scale correctly to multiple resolutions and aspect ratios. (Not all demos are suitable for this, but most demos should be.)

okapii commented 3 years ago

@Calinou Thanks for the feedback! Gonna give that a try!

akien-mga commented 2 years ago

As I understand it things are working as intended, but it's maybe not the most self explanatory behavior? Does it behave the same on macOS and on other OSes? Should we just document this better?

pseidemann commented 1 year ago

hi everyone :)

issue confirmed with v3.5.1.stable.official [6fed1ffa3].

@akien-mga, I think it's not intended once you are trying to create a gui application (like the godot editor itself).

imho there are multiple aspects which need to be considered.

what is allow hidpi currently doing? it disables scaling of the viewport by the os. it also enables rendering it at the native resolution. this implies that when e.g. a system has 2x scaling (example: display is 4k but user wants desktop size to be logical 1080p), the project will be rendered 2x too small when not doing anything special about that.

what are gui applications? a gui application is usually a project which uses mostly only control nodes. examples would be the godot editor itself or your favorite browser.

how should gui applications behave regarding scaling? gui applications should have a proper control element size when starting the app and this size must stay the same regardless of the window size (different from games where fullscreen is often desired so the window size can be "predicted").

what is the behavior with default settings? gui applications are properly scaled, though it could be argued that they don't render at native resolution, which MIGHT look blurry on some systems. also I was told that there is some windows bug which is not fixable by godot which breaks window scaling (especially on multi monitor setups?).

gui application: allow hidpi + fix scaling? I was told to enable stretch mode 2d but this is however NOT a solution because this breaks a fundamental principle how gui applications work. this would make control sizes dependent of the window size. see how should gui applications behave regarding scaling?.

I also ran into that issue while doing an unrelated fix for a godot demo but I couldn't get a good answer to that problem yet: https://github.com/godotengine/godot-demo-projects/pull/791

my conclusion is that currently "allow hidpi" is broken for gui applications. in fact that is also what the guide "multiple resolutions" is stating: https://docs.godotengine.org/en/stable/tutorials/rendering/multiple_resolutions.html

imho a fix might be worth here. maybe implementing dynamic scaling like the godot editor does.

another source: this person on q&a also explains the issue very well but the given answer doesn't fix the issues I mentioned here: https://godotengine.org/qa/89180/whats-the-right-way-to-support-hidpi

pseidemann commented 8 months ago

still a problem in godot 4