macOS: Expose more display modes on retina screens. Fixes an issue found in BZFlag.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
diff --git a/src/video/cocoa/SDL_cocoamodes.m b/src/video/cocoa/SDL_cocoamodes.m
index c8c0322..d7fb0fd 100644
--- a/src/video/cocoa/SDL_cocoamodes.m
+++ b/src/video/cocoa/SDL_cocoamodes.m
@@ -100,15 +100,47 @@ CG_SetError(const char *prefix, CGDisplayErr result)
}
static SDL_bool
-GetDisplayMode(_THIS, CGDisplayModeRef vidmode, CVDisplayLinkRef link, SDL_DisplayMode *mode)
+GetDisplayMode(_THIS, CGDisplayModeRef vidmode, CFArrayRef modelist, CVDisplayLinkRef link, SDL_DisplayMode *mode)
{
SDL_DisplayModeData *data;
- int width = 0;
- int height = 0;
+ int width = (int) CGDisplayModeGetWidth(vidmode);
+ int height = (int) CGDisplayModeGetHeight(vidmode);
int bpp = 0;
int refreshRate = 0;
CFStringRef fmt;
+ /* Ignore this mode if it's low-dpi (@1x) and we have a high-dpi mode in the
+ * list with the same size in points.
+ */
+#ifdef MAC_OS_X_VERSION_10_8
+ if (modelist != NULL && floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_7) {
+ int pixelW = (int) CGDisplayModeGetPixelWidth(vidmode);
+ int pixelH = (int) CGDisplayModeGetPixelHeight(vidmode);
+
+ if (width == pixelW && height == pixelH) {
+ CFIndex modescount = CFArrayGetCount(modelist);
+
+ for (int i = 0; i < modescount; i++) {
+ CGDisplayModeRef othermode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modelist, i);
+
+ if (CFEqual(vidmode, othermode)) {
+ continue;
+ }
+
+ int otherW = (int) CGDisplayModeGetWidth(othermode);
+ int otherH = (int) CGDisplayModeGetHeight(othermode);
+
+ int otherpixelW = (int) CGDisplayModeGetPixelWidth(othermode);
+ int otherpixelH = (int) CGDisplayModeGetPixelHeight(othermode);
+
+ if (width == otherW && height == otherH && (otherpixelW != otherW || otherpixelH != otherH)) {
+ return SDL_FALSE;
+ }
+ }
+ }
+ }
+#endif
+
data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
if (!data) {
return SDL_FALSE;
@@ -116,8 +148,6 @@ GetDisplayMode(_THIS, CGDisplayModeRef vidmode, CVDisplayLinkRef link, SDL_Displ
data->moderef = vidmode;
fmt = CGDisplayModeCopyPixelEncoding(vidmode);
- width = (int) CGDisplayModeGetWidth(vidmode);
- height = (int) CGDisplayModeGetHeight(vidmode);
refreshRate = (int) (CGDisplayModeGetRefreshRate(vidmode) + 0.5);
if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels),
@@ -243,7 +273,7 @@ Cocoa_InitModes(_THIS)
SDL_zero(display);
/* this returns a stddup'ed string */
display.name = (char *)Cocoa_GetDisplayName(displays[i]);
- if (!GetDisplayMode(_this, moderef, link, &mode)) {
+ if (!GetDisplayMode(_this, moderef, NULL, link, &mode)) {
CVDisplayLinkRelease(link);
CGDisplayModeRelease(moderef);
SDL_free(display.name);
@@ -340,7 +370,29 @@ void
Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
{
SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
- CFArrayRef modes = CGDisplayCopyAllDisplayModes(data->display, NULL);
+ CFDictionaryRef dict = NULL;
+ CFArrayRef modes;
+
+ /* By default, CGDisplayCopyAllDisplayModes will only get a subset of the
+ * system's available modes. For example on a 15" 2016 MBP, users can
+ * choose 1920x1080@2x in System Preferences but it won't show up here,
+ * unless we specify the option below.
+ */
+#ifdef MAC_OS_X_VERSION_10_8
+ if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_7) {
+ const CFStringRef dictkeys[] = {kCGDisplayShowDuplicateLowResolutionModes};
+ const CFBooleanRef dictvalues[] = {kCFBooleanTrue};
+ dict = CFDictionaryCreate(NULL,
+ (const void **)dictkeys,
+ (const void **)dictvalues,
+ 1,
+ &kCFCopyStringDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+#endif
+
+ modes = CGDisplayCopyAllDisplayModes(data->display, dict);
+ CFRelease(dict);
if (modes) {
CVDisplayLinkRef link = NULL;
@@ -352,7 +404,7 @@ Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
for (i = 0; i < count; i++) {
CGDisplayModeRef moderef = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
SDL_DisplayMode mode;
- if (GetDisplayMode(_this, moderef, link, &mode)) {
+ if (GetDisplayMode(_this, moderef, modes, link, &mode)) {
CGDisplayModeRetain(moderef);
SDL_AddDisplayMode(display, &mode);
}