Reported Width and Height of GameWindow is scaled by the Windows DPI scaling.
This is correct, but there is no way to know what the non-scaled Width and Height are set to. This is useful when saving the window size and position.
Example: Create a window with size 640 by 480. Windows desktop DPI scaling is set to 150%. GameWindow width is 960 and height is 720 which is correct. If we save those values and use them upon next start, the window will grow another 150% in size.
Maybe there could be new properties such as UnscaledWidth and UnscaledHeight.
Thanks for the bug report, this is indeed an issue. Neither OpenTK nor SDL handle resolution independence correctly right now, but this is something I would like to fix for the 1.1 release. Unfortunately, finding an acceptable solution is a bit more challenging than it looks.
Before I dive into the details, a workaround for your use case: calculate the current DPI scale factor and divide Width and Height by that before saving to disk:
var gw = new GameWindow(width, height);
var scale = gw.Width / (float)width; // derive current DPI scale factor
This way, you save unscaled values to disk and the size is correct upon next start.
Now to the meat of the issue. The problem is that each platform behaves slightly differently under DPI scaling:
Here is how the current situation looks like in OpenTK:
Considering the above, a hypothetical UnscaledWidth/Height API would work on Windows but fail horribly on Mac OS: a 200% 1280x800 window would return 2560x1600 unscaled size. Passing 2560x1600 to the GameWindow constructor would result in a window 4x bigger than desired!
I'm open to suggestions on how to solve this mess.
Maybe someone with more experience writing DPI-aware cross-platform apps could pitch in here.
Thanks for the workaround! It is working very good. Also, thanks for the high DPI support. It has been on my wishlist for a while.
Cross platform scaling sounds like quite a quandary. I think there are benefits to both using points and pixels and both would work good. Given that OpenGL seems to work on a pixel level for many operations such as glViewport(int, int, int, int), pixels seem like a logical choice. This also works well with the current API where the mouse X & Y are integers. There is also the consideration that certain effects can be obtained by knowing the actual pixels on the screen such as sub-pixel aliasing.
Yes, I think Option (1), which is basically to make all OpenTK HiDPI work like it does on the Mac today, is a sane option. I say this, because this probably produces the most sane "common case result" -- namely, applications which present themselves at the user-choosen scale size when the developer didn't handle HiDPI. I don't think this should affect full-screen options, so the "desktop resolution" being scaled shouldn't much matter as users won't see this anyhow.
The tradeoff here is that non-HiDPI aware apps may have slightly blurry 2d HUD fonts.. I think this is a more sane option than having the entire HUD be tiny in the case of 2x HiDPI displays.
IMHO leave it as is for compatibility and instead do 2 things:
You cant "leave it as is" because right now you can only make hidpi opentk apps work properly on either mac or windows. The goal should be for the common opentk source patterns to work correctly out of the box with hidpi or not.
Option 1 will give opentk apps sane behavior on both mac and windows, hidpi or not. Windows recommendations should be ignored as their hidpi support is still a mess.
It's just important to also expose the raw unscaled desktop res, window res, and coords.. So apps that want to custom support hidpi can do it. (Best practice is to render 3d at a lower resolution, but 2d at native screen resolution.. Which takes sme custom cosing)
We have been having some issues with this as well, but so far I have not been able to fix the problem apart from telling Windows not to use DPI scaling in the compatibility settings of the executable.
The workaround @thefiddler posted above also does not seem to do anything for us. The window reports to be the same size that I told it to be, even though I have scaling set to 200% right now. (And the window is ridiculously big and blurry accordingly.) And this is the same, whether I tell windows to enable or disable scaling for the application. (This is all on Windows 8.1.)
Regarding the two options given, from a game developer's perspective, I would much rather have control over my window on a per-pixel basis, so that I can render as pixel-perfect as I want. If there is up-scaling to be done, I would prefer being in charge of that myself (and in terms of games, especially on PC, exposing relevant settings to the user; a significant number of them prefers to be in full control of their games' settings).
I can see @jeske's point though and as long as enough info is exposed for me to do my own thing, I am fine.
One other point, that may or may not be related (if you think it is not, let me know and I'll make another issue):
We have a couple of customer complaints reporting that our game runs in less than full-screen size when they toggle on fullscreen mode. I use a bunch of custom code for that, but in essence I get the bounds of the DisplayDevice and set the bounds of my window to the same value.
What confuses me is that when I set my scaling to 200%, the window gets much larger than my screen. The users in question report that their window is too small though, which sounds like they have less than 100% scaling, which is not supported by Windows however. Further it makes little sense to me, since they would essentially be unable to read any text on their screen.
The only other bit of information I have right now is that the people in question all seem to use screens with larger than fullHD resolutions. I do not see what could go wrong with that though. While I cannot test on larger than fullHD myself, I can resize the window to be larger than that, and neither OpenTK nor OpenGL have any issues with that.
I've got a Win7 desktop and Win8.1 laptop at home so I can do some DPI tests on Windows. Looks like some MSDN reading is in order.
If others can help with the OSX and Linux stories (especially OSX, I have a Linux box at work I can test on but no access to OSX machines), we can see about trying to unify behaviour across all platforms.
Agree with @amulware that it should be possible to see raw (unscaled) values, and control pixel perfect results.
The reason I support option-1 (using scaled pixels in all the default APIs) is that it produces the most sane behavior on the widest variety of systems and hardware "without extra work". When you have real hidpi displays, most games will not run reasonably with HiDPI 3d surface sizes, because of fill rate limits. For example, the MacBook Pro Retina is a laptop with 2880x1800. The mobile GPU can't push that many pixels in 3d rendering at reasonable FPS. The same is true of HiDPI windows laptops.
An important subtlety is how to detect HiDPI on windows (and eventually Linux), and when to treat everything as Native Pixels vs HiDPI scaled. For example, a user who sets the Windows UI Scale to (say 110% or 120%) should get a native-pixels OpenTK Game Window. However, one with 180% or 220% is most-likely on a HiDPI display and should get a scaled window. Alternatively, I believe windows has a DPI value you can query, independent of UI scaling. However, I'm not sure if that is reliable.
When developers want to do the extra work to support HiDPI, they should be able to see everything raw and also write cross-platform native pixels sizes with OpenTK Game Window. For example, my HiDPI plan is to render the 3d surface to an FBO at about 1/2 native HiDPI pixel count, but to render the 2d HUD at native HiDPI pixels ontop of the 3d surface. (For example, on MBP-retina, I'll render 3d at 1440x900, underneath HUD items with native 2880x1800 pixels. AFAIK, Arma and Diablo are two few titles to support separate 3d and 2d resolutions)