-
Notifications
You must be signed in to change notification settings - Fork 903
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement high-DPI support on Windows #332
Conversation
src/platform/windows/monitor.rs
Outdated
@@ -79,13 +82,19 @@ unsafe extern "system" fn monitor_enum_proc(hmonitor: winapi::HMONITOR, _: winap | |||
impl EventsLoop { | |||
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> { | |||
unsafe { | |||
// We need to enable DPI awareness to get correct resolution and DPI of each monitor. | |||
dpi::become_dpi_aware(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You put tabs instead of spaces on these two lines only.
Here’s a report from my environment (Windows 10 Insider Preview, i.e. Fall Creators Update; Surface Book 2× display plus two external 1× displays). I can confirm that this seems to fire all the appropriate events and generally behave reasonably including coping with moving the window between screens. Multiple windows are handled appropriately, with each window scaling appropriately independently. Sadly running the examples seems to want to open them on the primary display only, rather than on the last display they were open in (which is what Windows generally tries to do), so I can’t confirm what it’s like when it starts on a different display. DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE leads to the client dimensions of the window changing (the increased edges and title bar widths are taken out of the window size, and it seems to still be about ten pixels smaller horizontally and five vertically than I’d expect taking that into account, not certain what that’s about). Definitely not ideal. DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 doesn’t suffer from this weakness (but I haven’t tried it on anything that uses a glViewport). Here are probably-unnecessary screenshots of moving the Note the change in window size at 1×, as noted earlier.
The black I presume is a side-effect of the examples/window.rs not doing any drawing, since you get the same effect from increasing the window size. That the initial content is drawn white but any later areas become black has made me curious, but it’s hardly relevant. Certainly it looks prettier with DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 (the title bar being scaled appropriately; and the internal window dimensions then stay the same when moved from the 2× to the 1× display), but given that a glViewport is what you complained of and examples/window.rs doesn’t do that… yeah. Got something I could conveniently test or experiment with? I was interested to note that with both regular and _V2 per-monitor awareness, when the window comes back to the 2× display it’s half an display pixel taller (i.e. 829px rather than 828px). |
I don't like the |
@chris-morgan I've made an OpenGL app to test high-DPI support. It should correctly handle high-DPI and respond to DPI changes. Turns out the issue with |
@chris-morgan It seems that winit does not support specifying on which monitor to create window. |
@tomaka This is a better solution indeed, I changed my implementation to use |
@kryptan Thanks for that example; it messes with my eyes at 2×, well done! I’ll probably be able to play with it in a mixed-DPI environment on Saturday evening (GMT+11), as I’ll be away from my low-DPI monitors until then. Knowing how these things often go, that means don’t count on it until at least Monday… or next month… My Surface Book has both Intel and nVidia GPUs, so I can also try it out with both. (You know what I’d really like? Apps that could switch between the two at will, so that they could use the nVidia GPU while the base was attached and seamlessly switch to the other when detaching the screen from the base. No idea how technically feasible that actually is. Anyway, that’s a digression.) |
I updated my Intel drivers and now it is different. Now I don't have issues with V2 awareness when changing DPI scaling in Windows settings, but when I move window to another monitor I get garbage regardless of whether V2 or V1 awareness is used. We might want to report it to Intel, in my experience they are responsive on their forum. |
… and that’s a substantial part of why GPU rendering for general purpose applications hasn’t taken off. ☹ (The remainder is that without things like webrender and UI toolkits built on top of that, it’s harder!) |
Also add call to EnableNonClientDpiScaling to enable non-client scaling even if V2 is not available
I changed PR to use |
Running your dpi-test against your latest patch from this PR, with the Intel GPU (renderer “Intel(R) HD Graphics 520”, version “4.4.0 - Build 20.19.15.4463”): And moved to the low-DPI display: (Shifting it to the low-DPI display with Win+Shift+Left changes its resolution from 1026×758 to 486×758, which corresponds to the different aspect ratio of that screen, but still surprises me.) NVIDIA GPU (renderer “GeForce GPU/PCIe/SSE2”, version “4.5.0 NVIDIA 376.67”) at 2×: And at 1×: (On the Intel GPU, everything’s buttery-smooth; on the NVIDIA GPU which is generally 2–3× as powerful in my experience, initial rendering takes the best part of a second—presumably spinning the GPU up takes a short time—and resizing is a little slow, with rendering being at least a frame or two behind the resize with regular brief glitches. No idea whose fault that may be.) |
Latest Intel driver released on November 7 fixes the issue: https://downloadcenter.intel.com/download/27266/Graphics-Intel-Graphics-Driver-for-Windows-15-60-?product=88355 @chris-morgan can you please test it on your system and confirm? For me it works fine. |
I tested this only on Windows 10. A also tested codepaths for older Windows versions by commenting out code for newer versions.
Currently it uses the
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
mode on Windows 10. There is also newer and betterDPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
but I had an issue with it.V2
enables correct scaling of window's non-client area (title bar and borders) butglViewport
is then unable to correctly set viewport and works as if non-client area was not scaled. I see nothing wrong in winit or glutin so I suspect that this is a bug in either Windows or in OpenGL drivers (I have latest NVidia drivers installed). Before updating to the latest NVidia drivers I also had another issue where moving window from one monitor to another with different DPI would make it black (at least when using glutin), however it was fixed after driver update.cc @retep998