Skip to content
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

High DPI, Retina Mac #3757

Open
cmaughan opened this issue Jan 25, 2021 · 16 comments
Open

High DPI, Retina Mac #3757

cmaughan opened this issue Jan 25, 2021 · 16 comments

Comments

@cmaughan
Copy link
Contributor

Version/Branch of Dear ImGui:
Version: 1.80
Branch: docking

Back-ends: imgui_impl_opengl3.cpp + imgui_impl_sdl.cpp
Operating System: Mac/Win

My Issue/Question:

On Windows, with a 4K display, using SDL + GL3 backends, I get a tiny view of ImGui. This is easily fixed by getting the DPI scale of the monitor (SDL_GetDisplayDPI(....) / 96.0f), and using this value to scale the font:

`io.Fonts->AddFontFromFileTTF(..., 16.0f * dpi_scale);`

Note that on Windows, you also need to add the manifest file to make sure that the app is DPI aware.
Calling SDL_GetWindowSize with this configuration returns the same values as SDL_GetDrawableSize:

SDL_GetWindowSize = 100, 100
SDL_GetDrawableSize = 100, 100
DisplayFramebufferScale = 1

So, for example, a 100x100 window, will have a drawable of 100x100 and a window size on screen of 100x100, and although SDL_GetDisplayDPI returns 2, our DisplayFramebufferScale is now 1: everything is rendered at high DPI and we are happy, with 1:1 pixels on the screen.

Removing the manifest and using OS DPI scaling, our window is now visibly twice the size on screen, but our values for window size and drawable size are the same. Our DisplayFramebufferScale is still 1, but SDL_GetDisplayDPI scales 1, because the OS is lying to us and scaling everything up under the covers. Our fonts are blurry because we are technically scaling them up from a 100 to a 200 sized window. All good, as expected.

Here's the problem. On MacOS, with the same scenario, including a valid plist, and setting NSHighResolutionCapable, etc. the numbers that come back from SDL are different. This time, we get:

SDL_GetWindowSize = 100, 100
SDL_GetDrawableSize = 200, 200
Get_DisplayDPI / 96 = 2 (actually 2.5 on my MBP 16" system, but lets keep it simple...)
FrameBufferScale = 2
io.DisplaySize = 100, 100

And later in glViewport we set the size to io.DisplaySize. This is a problem because now, although we created a high DPI framebuffer, the viewport is rendering to 1/4 of it. And later we are zooming it up from 100x100 to 200x200 (the real size of the window). Blurry fonts.

Adding a hack to NewFrame to set DisplaySize = DrawableSize will fix the rendering, give me high resolution fonts as long as I scale the font size by DPI. But now something about the mouse logic is confused and I can't move viewports around/interact with the UI.

At this point, I'm stuck as to how to fix the mouse logic; and how to fix this in a universal way that makes sense. This behavior must have been seen before; I hope my explanation of what's going on here helps....

@cmaughan
Copy link
Contributor Author

To be clear, the fundamental difference here is that SDL on Mac is returning the 'fake' window size, not the real window size in pixels when in high DPI mode. On Windows, we get the real window size when in high DPI - i.e the pixel dimensions.

@ocornut
Copy link
Owner

ocornut commented Jan 25, 2021

Hello Chris,

I'm not in the headspace to give a fully detailed answer, as you found out is a slightly wide and multi-headed topics. OSX does indeed report different window size from framebuffer size, Windows does not. I think the best action is we should aim eventually to make all examples DPi aware (at least for single viewport), maybe it'll be a nice target to tackle for ~1.82.

Note that on Windows, you also need to add the manifest file to make sure that the app is DPI aware.

There are other ways, namely in imgui_impl_win32 the ImGui_ImplWin32_EnableDpiAwareness() gives an equivalent result without requiring a manifest and without requiring SDK 10 at compile-time or Windows 7 at run-time.
You can call ImGui_ImplWin32_EnableDpiAwareness() before initializing SDL/GLFW and it would work there too.

Maybe the https://github.com/ocornut/imgui/issues?q=+label%3Adpi+ tag can also be helpful.

@cmaughan
Copy link
Contributor Author

Thanks, yup, this is a minefield alright, and requires a lot of test setup to go through the combinations. I don't mind the manifest/plist; but good to know about the other APIs.

It is the mouse interaction I'm stuck on. I might get some more time to delve into this tonight. It certainly isn't obvious at the moment!

@ocornut
Copy link
Owner

ocornut commented Jan 25, 2021

It's even more of a mess when you start digging in multi-viewports territory.....
https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-how-should-i-handle-dpi-in-my-application

I think we need to focus on a simple path to get examples working. I'll try to let you a path.

For live DPI change, Backends should support texture update requests (we have done work on this side on a private repo, its surprisingly hairy if you include in-flight textures, the possibility of rewriting already used pixels) - all this work will be extremely useful not only for base DPI handling but for dynamic font atlas.

@slajerek
Copy link

slajerek commented Mar 17, 2021

Actually, I am struggling with the same problem, and some proper code example for SDL Backend would be good to have.

Temporarily I have this patch applied:
a843af4

Especially this part of code seems to be enough:

//draw_data->FramebufferScale = ImGui::GetIO().DisplayFramebufferScale; // FIXME-VIEWPORT: This may vary on a per-monitor/viewport basis?
    if (g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)
	    draw_data->FramebufferScale = ImVec2(viewport->DpiScale, viewport->DpiScale);
	else
	    draw_data->FramebufferScale = g.IO.DisplayFramebufferScale;

Note also, in some older SDL versions getting the DPI on macOS by SDL_GetDisplayDPI was broken and actually it is still not correctly fixed: https://bugzilla.libsdl.org/show_bug.cgi?id=4856

Which actually made it really hard to understand what is going on as we had to comply with two issues at once.

Anyway, the above works to some extent but as @cmaughan said the fonts are blurry. I've seen some code done in recent docking branch to include support for freetype library, I've added this but still, fonts are blurry because freetype currently does not support oversampling.

Anyway, having a proper, working example for HighDPI would be really awesome as the blurry fonts are unfortunately still there and my users are asking me why we can't simply have good looking fonts...

@cmaughan
Copy link
Contributor Author

cmaughan commented Mar 17, 2021

Hi @slajerek, @ocornut

As I mentioned above it is possible to get High DPI working with a couple of hacks on Mac. I recently did an experimental GUI for Sonic Pi, and it has the necessary fixes. These are just workarounds, but solved the problem for now.

This change gives you a high DPI frame buffer on Mac:
FrameBuffer

These changes fix the mouse interaction:
Mouse 1

Mouse 2

@cmaughan
Copy link
Contributor Author

cmaughan commented Mar 17, 2021

They are protected in the #if APPLE sections; and note that you also need the plist/manifest stuff to get things to work in the first place, along with the high DPI flag on window create in SDL.

@krupkat
Copy link

krupkat commented Aug 27, 2022

If anyone would like to use the fix from @cmaughan with a more recent version of ImGui, I have recently had success with that, using the latest docking branch. The fix is in 216f654.

Thank you @cmaughan for publishing your fix here!

krupkat added a commit to krupkat/xpano that referenced this issue Aug 27, 2022
* build script for macos

* Switch to ImGui fork with fixed highdpi on Mac

See ocornut/imgui#3757 for details

* Revert dpi scaling constant

* Fix for compatibility with SDL 2.24.0 on Mac

* Switch to fmt#udt for clang compatibility

https://fmt.dev/latest/api.html#udt

* undo lapack disable

seems to be working on Mac

* Add macos build workflow

* fix opencv version in macos workflow

* Update readme and site about MacOS build
@cmaughan
Copy link
Contributor Author

cmaughan commented Sep 3, 2022

You're welcome @krupkat - glad it works for you.

@slajerek
Copy link

slajerek commented Sep 4, 2022

@cmaughan I think there's a small bug in this code

            } else {
#if defined(__APPLE__)

shouldn't it be

#if defined(__APPLE__)
            } else {

?

I am integrating this. Wow, at first the outcome is that all is very small. So it works, that's what my users reported all the time for Windows platform, that default theme is very small :) check these both screenshots, looks OK, but indeed the theme needs to be updated:
Screenshot 2022-09-04 at 05 32 07
Screenshot 2022-09-04 at 06 45 34

@Grieverheart
Copy link

Grieverheart commented Jan 11, 2023

@cmaughan Thank you for your solution. I tried it out and was happy to see the fonts not being blurry. Now, when I tried the example, there where differences in positioning and sizing of the windows, as you can see below. Is this normal?
Screenshot 2023-01-11 at 14 46 48
Screenshot 2023-01-11 at 14 46 16
I don't have experience with Imgui yet, but I'd like to use it in my project. Sharp fonts are really important to me, though :) .

@cmaughan
Copy link
Contributor Author

@cmaughan Thank you for your solution. I tried it out and was happy to see the fonts not being blurry. Now, when I tried the example, there where differences in positioning and sizing of the windows, as you can see below. Is this normal? Screenshot 2023-01-11 at 14 46 48 Screenshot 2023-01-11 at 14 46 16 I don't have experience with Imgui yet, but I'd like to use it in my project. Sharp fonts are really important to me, though :) .

Not sure; maybe you reloaded a saved layout and it wasn't remapped to the new DPI?

@bhundt
Copy link

bhundt commented Mar 27, 2023

Hi everybody,I know that this topic has been discussed a lot and I a read and googled a bunch but unfortunately I am stuck with the following problem:

I am using ImGui docking branch (commit bf87fbc), ImplSDL2 and ImplOpenGL3. SDL2 is installed with version 2.26.4 and I am working on a M1 Macbook with Ventura 13.2.1. When I enable docking and viewports and I switch SDL2 to high dpi mode I was able to use the fix by @krupkat for successful rendering. BUT my mouse interaction is still broken. In the following screenshot you see where my mouse is pointing (approximated with the red arrow) and you see the mouse position identified by ImGui by the highlighted item in the ImGui Demo Window.

image

I addition when I am dragging a window out of my main window, all ImGui windows get very large AND the mouse interaction works correctly:

Screenshot 2023-03-27 at 08 20 33

vs.

Screenshot 2023-03-27 at 08 21 22

I am scaling the fonts globally and I call ScaleAllSizes().

I played around a lot in imgui_impl_sdl2.cpp to try to rescale multiple values of mouse positions, window positions and so on but I was utterly unable to come close to something which seemed right...any help is greatly appreciated!

@cmaughan
Copy link
Contributor Author

I'm not in front of it at the moment, but you might want to check that @krupkat got all of my changes in their update. Assuming they did, I've seen your problem before, and IIRC there are more places to apply my mouse scaling fixes in the docking branch than the regular one. Unfortunately I'm not setup on Mac, so that's all I can offer for now. I will update when I get chance to try it.
It is certainly past due for a proper fix in ImGui core; I imagine everyone hits this problem these days.

@krupkat
Copy link

krupkat commented Mar 27, 2023

You can check out this version from my fork: https://github.com/krupkat/imgui/releases/tag/docking_v1.89.4_wip
It is quite recent with the official docking branch.

The changes from the official branch are the one you linked: krupkat@216f654 and one more where I simplified it a bit and fixed similar issues on Linux: krupkat@80be499

I have previously tested on Mac and was successful, but didn't try multiviewport, maybe you can try without that feature.

@bhundt
Copy link

bhundt commented Mar 27, 2023

You can check out this version from my fork: https://github.com/krupkat/imgui/releases/tag/docking_v1.89.4_wip It is quite recent with the official docking branch.

The changes from the official branch are the one you linked: krupkat@216f654 and one more where I simplified it a bit and fixed similar issues on Linux: krupkat@80be499

I have previously tested on Mac and was successful, but didn't try multiviewport, maybe you can try without that feature.

Thanks for your feedback and also thanks @cmaughan. I just tried the branch you (@krupkat) mentioned and without Multi-Viewport mouse input works as expected.

Still the issue remains when using multiviewport. I tried to scale mouse and window positions in impl_sdl2.cpp where the code branches out depending on ImGuiConfigFlags_ViewportsEnable but the issue persists. So I guess the problem needs to be related to obtaining the mouse position in relation to the main window...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants