A few months ago I started getting reports of our game (BZFlag) failing to launch on certain mac computers. When I investigated it, I found that our code kept trying to create a fullscreen window at a certain resolution, but another resolution would be returned instead, so it was stuck in an endless cycle. As I dug deeper, what I discovered is that under certain conditions (retina display, with a non-standard scaling option under System Preferences -> Displays), SDL_GetCurrentDisplayMode() returns a resolution that isn’t actually supported by the display. What follows is that we cannot pass that resolution to SDL_CreateWindow() and get what we asked for.
I wrote a test application that queries SDL for the current display mode and every other possible display mode using SDL_GetNumDisplayModes() and SDL_GetDisplayMode(), and attempts to create a fullscreen window with SDL_CreateWindow() using each resolution. I then ran the test application on an Apple MacBook Pro retina 13" at all four scaling settings, with the following results:
skye:Desktop josh$ "Larger Text"
skye:Desktop josh$ ./a.out
Current Resolution 1024 x 640 FAIL, got 1024 x 768
Resolution 2560 x 1600 PASS
Resolution 2048 x 1280 PASS
Resolution 1650 x 1050 PASS
Resolution 1440 x 900 PASS
Resolution 1280 x 800 PASS
Resolution 1152 x 720 PASS
Resolution 1024 x 768 PASS
Resolution 840 x 524 PASS
Resolution 800 x 600 PASS
Resolution 640 x 480 PASS
skye:Desktop josh$ "Default"
skye:Desktop josh$ ./a.out
Current Resolution 1280 x 800 PASS
Resolution 2560 x 1600 PASS
Resolution 2048 x 1280 PASS
Resolution 1650 x 1050 PASS
Resolution 1440 x 900 PASS
Resolution 1280 x 800 PASS
Resolution 1152 x 720 PASS
Resolution 1024 x 768 PASS
Resolution 840 x 524 PASS
Resolution 800 x 600 PASS
Resolution 640 x 480 PASS
skye:Desktop josh$ "In Between"
skye:Desktop josh$ ./a.out
Current Resolution 1440 x 900 PASS
Resolution 2560 x 1600 PASS
Resolution 2048 x 1280 PASS
Resolution 1650 x 1050 PASS
Resolution 1440 x 900 PASS
Resolution 1280 x 800 PASS
Resolution 1152 x 720 PASS
Resolution 1024 x 768 PASS
Resolution 840 x 524 PASS
Resolution 800 x 600 PASS
Resolution 640 x 480 PASS
skye:Desktop josh$ "More Space"
skye:Desktop josh$ ./a.out
Current Resolution 1680 x 1050 FAIL, got 2048 x 1280
Resolution 2560 x 1600 PASS
Resolution 2048 x 1280 PASS
Resolution 1650 x 1050 PASS
Resolution 1440 x 900 PASS
Resolution 1280 x 800 PASS
Resolution 1152 x 720 PASS
Resolution 1024 x 768 PASS
Resolution 840 x 524 PASS
Resolution 800 x 600 PASS
Resolution 640 x 480 PASS
So it seems that what is being returned by SDL_GetCurrentDisplayMode() under certain scaling modes is not a resolution that the display can actually be put into. I poked around in SDL’s code for this function, and as far as I can tell it pulls this information straight from the operating system.
So my question is, is this the expected behavior for SDL_GetCurrentDisplayMode()? Is there a better way to get the true resolution currently in use when a retina display is in one of those scaling modes? Or if this is not the expected behavior, is the problem in SDL or more likely in the macOS operating system code? For reference, I demonstrated this issue on macOS Sierra 10.12.5 and SDL 2.0.5.
Specifically, it’s not clear that passing the fullscreen resolution to SDL_CreateWindow() is correct - the docs at https://wiki.libsdl.org/SDL_CreateWindow specifically state that the width/height params are ignored if you call it with SDL_WINDOW_FULLSCREEN (even though they are not ignored in practice).
It might be worth seeing if you can reproduce the problem by using SDL_SetCurrentDisplayMode instead of SDL_CreateWindow() .
I have a retina display Mac as well so would be interested in looking at this, mind posting the code for your test program?
Was able to reproduce and found a fix. The problem seems to have been code in SDL_cocoamodes.m using CGDisplayModeGetWidth which returns points instead of pixels when a scaled retina resolution is in use. That’s why you’re getting
Current Resolution 1024 x 640
for the “Larger Text” setting. The fix was just switching to CGDisplayModeGetPixelWidth/Height. I submitted a patch for this in the bugtracker:
I appreciate the effort to fix this issue. I personally don’t own a retina mac (I had to borrow one for my testing), so if someone with better access to such a machine could help test the fix, that would be much appreciated. As long as SDL_GetCurrentDisplayMode() returns a resolution that the screen can actually be put into, that will solve the problem on our end.