This is a little nasty..
I'm trying to keep all changes localised to imgui_impl_osx.mm
Ideally the ImGui_IO_lock would live within ImGuiIO but I didn't want to muddy the waters
Perhaps better if this lock primitive is delivered through BackendPlatformUserData, and only used where provided
This change requires the client platform to explicitly lock the primitive from outside of ImGui around ImGui::NewFrame specifically, and additionally from anywhere on the client side (external to ImGui) that concurrently hooks into ImGuiIO
That requires the client to define an extern lock (and use it appropriately)
extern NSlock *ImGui_IO_lock
If this lock were native to ImGui we could have ImGui::NewFrame() handle the lock on our behalf, negating the need for client side locking
This issue presents when rendering from a thread that is other than the window thread, more easily reproduced when disabling vsync
This commit aims to populate the relevant data into backend_data, by way of dispatch_async (ocurring on the main thread). Those particular backend data items are protected by an NSlock
There may be more elegant ways to do this
Main Thread Checker
imgui/backends/imgui_impl_osx.mm:608 -[NSView window] must be used from main thread only
imgui/backends/imgui_impl_osx.mm:608 -[NSWindow backingScaleFactor] must be used from main thread only
imgui/backends/imgui_impl_osx.mm:609 -[NSView bounds] must be used from main thread only
We can divide platforms into two cases based on how they report screen geometry:
- Case 1: Platforms which report screen size in "physical pixels": Windows (for "Dpi aware" apps), Linux (with Wayland)
- Case 2: Platforms which report screen size in "density-independent pixels": macOS, iOS, Android, emscripten
As a consequence, there are two important things we need to know:
- FramebufferScale: The scaling factor FrameBufferSize / ScreenSize
- In case 1, the framebuffer size is equal to the screen size and DisplayFramebufferScale=1.
- In case 2, the framebuffer size is equal to the screen size multiplied by a factor, for example DisplayFramebufferScale=2.
- ContentScale The scaling factor for the content that we will display
- In case 1, the content scale will often need to be > 1 (e.g., 2), because we will need to display bigger elements so that they show with a correct physical size on the screen.
- In case 2, the content scale is equal to 1
This commit fixes ContentScale for platforms in case 2.
Only the call to ImFontAtlasBuildSetupFontLoader() is the notable change. The change in ImFontAtlasFontInitOutput() is merely to use an existing helper function.