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.