Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Full Support for High-DPI Displays and DPI Awareness  (Read 15408 times)

0 Members and 1 Guest are viewing this topic.

thomas9459

  • Newbie
  • *
  • Posts: 49
    • View Profile
    • Email
Full Support for High-DPI Displays and DPI Awareness
« on: December 25, 2014, 04:26:41 am »
While SFML currently has partial support for high-DPI displays, their are some issues that cannot be resolved without making SFML's API DPI aware. I've done some research and compiled a list of links to how this is handled on various systems / libraries:
  • OS X - Comprehensive documentation for OS X
  • Windows - Introduction tutorial for Windows
  • Windows - Comprehensive documentation for Windows
  • iOS - Section from the iOS documentation
  • Android - Description for Android devices
  • GLFW- Small section describing DPI handling in GLFW
I was unable to find any good resources for Linux, but it seems like it is a limitation in X that prevents correct DPI awareness (although supposedly Wayland has support for it).

For those who are new to DPI awareness, I would highly recommend the introduction in the OS X documentation: it's not too long and explains the basic concept very well (and has pictures!).

For the most part, it seems like all the systems use the same basic design: window management, mouse coordinates, etc. use a more abstract system for screen coordinates, with various names being used for the measuring unit ("points", "density-independent pixels", "screen coordinates", etc.), whereas lower-level drawing commands ,including most interactions with OpenGL, using the actual pixel coordinates. Then a scaling factor is exposed in the API to convert between these two systems. Since SFML encompasses of these domains, it should make a distinction between these two systems in its own API.

I took the liberty of going through the SFML API and identifying the changes that would have to be made in order to make SFML fully DPI aware. First, the following would have to be changed to use screen coordinates rather than physical pixels (this includes making these values floats):

  • sf::Event::MouseButtonEvent: x, y
  • sf::Event::MouseMoveEvent: x, y
  • sf::Event::MouseWheelEvent: x, y
  • sf::Event::SizeEvent: width, height
  • sf::Event::TouchEvent: x, y
  • sf::Mouse: getPosition(), setPosition()
  • sf::VideoMode: width, height
  • sf::Window: getPosition(), setPosition(), getSize(), setSize()

The following should continue to use physical pixels:

  • sf::RenderTarget: getSize()
  • sf::RenderTexture
  • sf::Texture
  • sf::Image

Other classes in SFML (such as views, shapes, etc.) already use coordinate systems that are not tied to pixels/screen coordinates, and are thus not affected.

In addition to the above changes, the following should be added to the API:

  • Add the function sf::Window/RenderWindow::getScaleFactor() that would retrieve the current scaling factor for the window.
  • Change the default view generation for sf::RenderWindow so that it is based on screen coordinates rather than pixels. This way, the default view is independent of the DPI of the screen it was created on.
  • A scaling field should be added to sf::Event::SizeEvent for cases like when a window is moved between displays with different scaling factors. Alternatively, we could do similar to GLFW and create a new event type that deals exclusively with scaling events (sf::Event::ScaleEvent?).

There is one more modification that needs to be made that concerns sf::RenderWindow::getSize(). Since sf::Window::getSize() should use screen coordinates, as it is part of window management, and sf::RenderTarget::getSize() should use pixels, as it works with OpenGL, which way should sf::RenderWindow::getSize() go?  Here is a short list of ideas:

  • Rename the getSize() methods so that the one inherited form sf::Window is kept distinct from the one inherited from sf::RenderTexture.
  • Add a bool argument to getSize() to signal which version we want.
  • Exclude sf::RnderWindow::getSize() from the public API so the user has to explicitly specify render_window.Window::getSize() or render_window.RenderTarget::getSize().
  • Use composition rather than inheritance between sf::RenderTarget and sf::RenderWindow.

None of these options are very clean, however. I'm also not sure of all the other changes planned for SFML 3 though, so maybe they affect this issue somehow, hopefully for the better?

Two final notes: First, dynamic changes to the scaling, such as the user moving the window between two monitors with different scaling factors, does not require full multiple monitor support, as it is possible to query the current scaling factor for a given window directly (at least on OS X and Windows 8.1), so this does not depend on complete multiple monitor support in SFML.

Second, although above I called them physical pixels, it turns out that even what OpenGL works with does not always correspond to physical pixels on the screen. For example, on my Retina display MacBook, the virtual screen is 1440x900 and the physical screen is 2560x1600, but the scaling factor is 2.0x. This is because OS X renders everything to a framebuffer of 2880x1800, then scales it in hardware back to 2560x1600 for output. This happens well after SFML, or even OpenGL, is involved, and we aren't really supposed to be concerned with it, but it is interesting nonetheless.

Anyways, is full DPI awareness support something we should target for SFML 3? And, if so, is it too soon to start work on implementing it, especially considering that it does change quite a lot of types in the API?

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
Re: Full Support for High-DPI Displays and DPI Awareness
« Reply #1 on: December 26, 2014, 10:01:58 am »
Thanks for this very detailed description.  :)

Quote
Anyways, is full DPI awareness support something we should target for SFML 3?
Personally I'd say, yes.

Quote
And, if so, is it too soon to start work on implementing it, especially considering that it does change quite a lot of types in the API?
Yes, probably. Let's first see if other members have some feedback on the listed modifications.  ;)
SFML / OS X developer

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11038
    • View Profile
    • development blog
    • Email
Re: Full Support for High-DPI Displays and DPI Awareness
« Reply #2 on: October 05, 2017, 02:44:19 pm »
Can't believe that this already close to 3 years old. :D

In the meantime I've got my hands on a high DPI notebook and thus can actually test how SFML handles it.

While a clean API solution can only be achieved in SFML 3, I think there's the possibility of creating an alternative API and if needed deprecate the old API.

One thing, that does seem kind of important is to at least provide the scaling factor, with which one can calculate the correct view vs window size.

I can't make any promises, but I hope to look into this a bit more, at first mostly to check reported issues with the current implementation and later to see what options there are. :)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
Re: Full Support for High-DPI Displays and DPI Awareness
« Reply #3 on: October 09, 2017, 04:17:45 pm »
Nice, let us know if you make progress toward a better API! I believe this would make sense to introduce some kind of `sf::Screen` type and change more than the resolution-related features, e.g. on which monitor you want to open the window depending on the screen resolution and so on.
SFML / OS X developer

Turbine

  • Full Member
  • ***
  • Posts: 100
    • View Profile
Re: Full Support for High-DPI Displays and DPI Awareness
« Reply #4 on: October 18, 2017, 06:20:22 am »
Please do, my character is half a millimetre on my Surface Pro 4. At least the DPI awareness part.

jvillasante

  • Newbie
  • *
  • Posts: 2
    • View Profile
    • Email
Re: Full Support for High-DPI Displays and DPI Awareness
« Reply #5 on: April 09, 2018, 08:55:16 pm »
Any advances on this?
SFML is unusable on OsX without support for High DPI

Jonny

  • Full Member
  • ***
  • Posts: 114
    • View Profile
    • Email
Re: Full Support for High-DPI Displays and DPI Awareness
« Reply #6 on: April 10, 2018, 07:08:57 pm »
SFML is unusable on OsX without support for High DPI

If you create an app bundle and modify the info.plist so "High Resolution Capable" is set to "NO", it will be usable, but I agree it's a massive hindrance on macOS right now

jvillasante

  • Newbie
  • *
  • Posts: 2
    • View Profile
    • Email
Re: Full Support for High-DPI Displays and DPI Awareness
« Reply #7 on: April 10, 2018, 07:20:44 pm »
I ended up creating a scale factor on OsX `const int SCALE_FACTOR = 2` then I scale everything by that scale factor. Bummer is that for fixed time steps you also need to scales your velocities and the like.

I'm just starting with SFML on OsX using emacs + cmake, it is hard to create a bundle like that.

Thanks anyways.

Jonny

  • Full Member
  • ***
  • Posts: 114
    • View Profile
    • Email
Re: Full Support for High-DPI Displays and DPI Awareness
« Reply #8 on: April 12, 2018, 01:16:38 am »
I also use CMake, here's an example of how I create an app bundle:

https://github.com/JonnyPtn/SFML-DOOM/blob/master/CMakeLists.txt#L33