Fix high-dpi support on macOS and simplify it and iOS variant. The detault drawableSize for a CAMetalLayer is its bounds x its scale. So it is sufficient to set the *layer's* scale to the desired value.
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 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
diff --git a/include/SDL_video.h b/include/SDL_video.h
index 28fc4c3..83f49fa 100644
--- a/include/SDL_video.h
+++ b/include/SDL_video.h
@@ -110,7 +110,9 @@ typedef enum
SDL_WINDOW_MOUSE_FOCUS = 0x00000400, /**< window has mouse focus */
SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ),
SDL_WINDOW_FOREIGN = 0x00000800, /**< window not created by SDL */
- SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000, /**< window should be created in high-DPI mode if supported */
+ SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000, /**< window should be created in high-DPI mode if supported.
+ On macOS NSHighResolutionCapable must be set true in the
+ application's Info.plist for this to have any effect. */
SDL_WINDOW_MOUSE_CAPTURE = 0x00004000, /**< window has mouse captured (unrelated to INPUT_GRABBED) */
SDL_WINDOW_ALWAYS_ON_TOP = 0x00008000, /**< window should always be above others */
SDL_WINDOW_SKIP_TASKBAR = 0x00010000, /**< window should not be added to the taskbar */
diff --git a/include/SDL_vulkan.h b/include/SDL_vulkan.h
index 803b5fe..d238e22 100644
--- a/include/SDL_vulkan.h
+++ b/include/SDL_vulkan.h
@@ -240,6 +240,9 @@ extern DECLSPEC SDL_bool SDLCALL SDL_Vulkan_CreateSurface(
* platform with high-DPI support (Apple calls this "Retina"), and not disabled
* by the \c SDL_HINT_VIDEO_HIGHDPI_DISABLED hint.
*
+ * \note On macOS high-DPI support must be enabled for an application by
+ * setting NSHighResolutionCapable to true in its Info.plist.
+ *
* \sa SDL_GetWindowSize()
* \sa SDL_CreateWindow()
*/
diff --git a/src/video/cocoa/SDL_cocoametalview.h b/src/video/cocoa/SDL_cocoametalview.h
index 131dad5..c0a582f 100644
--- a/src/video/cocoa/SDL_cocoametalview.h
+++ b/src/video/cocoa/SDL_cocoametalview.h
@@ -41,11 +41,10 @@
@interface SDL_cocoametalview : NSView {
NSInteger _tag;
- bool _useHighDPI;
}
- (instancetype)initWithFrame:(NSRect)frame
- useHighDPI:(bool)useHighDPI;
+ scale:(CGFloat)scale;
/* Override superclass tag so this class can set it. */
@property (assign, readonly) NSInteger tag;
diff --git a/src/video/cocoa/SDL_cocoametalview.m b/src/video/cocoa/SDL_cocoametalview.m
index 43e2636..e9c08a0 100644
--- a/src/video/cocoa/SDL_cocoametalview.m
+++ b/src/video/cocoa/SDL_cocoametalview.m
@@ -57,17 +57,19 @@
}
- (instancetype)initWithFrame:(NSRect)frame
- useHighDPI:(bool)useHighDPI
+ scale:(CGFloat)scale
{
if ((self = [super initWithFrame:frame])) {
+ _tag = METALVIEW_TAG;
self.wantsLayer = YES;
/* Allow resize. */
self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
- _tag = METALVIEW_TAG;
- _useHighDPI = useHighDPI;
- [self updateDrawableSize];
+ /* Set the desired scale. The default drawableSize of a CAMetalLayer
+ * is its bounds x its scale so nothing further needs to be done.
+ */
+ self.layer.contentsScale = scale;
}
return self;
@@ -77,16 +79,6 @@
- (void)resizeWithOldSuperviewSize:(NSSize)oldSize
{
[super resizeWithOldSuperviewSize:oldSize];
- [self updateDrawableSize];
-}
-
-- (void)updateDrawableSize
-{
- NSRect bounds = [self bounds];
- if (_useHighDPI) {
- bounds = [self convertRectToBacking:bounds];
- }
- ((CAMetalLayer *) self.layer).drawableSize = NSSizeToCGSize(bounds.size);
}
@end
@@ -94,12 +86,26 @@
SDL_cocoametalview*
Cocoa_Mtl_AddMetalView(SDL_Window* window)
{
- SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+ SDL_WindowData* data = (__bridge SDL_WindowData *)window->driverdata;
NSView *view = data->nswindow.contentView;
-
+ CGFloat scale = 1.0;
+
+ if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
+ /* Set the scale to the natural scale factor of the screen - then
+ * the backing dimensions of the Metal view will match the pixel
+ * dimensions of the screen rather than the dimensions in points
+ * yielding high resolution on retine displays.
+ *
+ * N.B. In order for backingScaleFactor to be > 1,
+ * NSHighResolutionCapable must be set to true in the app's Info.plist.
+ */
+ NSWindow* nswindow = data->nswindow;
+ if ([nswindow.screen respondsToSelector:@selector(backingScaleFactor)])
+ scale = data->nswindow.screen.backingScaleFactor;
+ }
+
SDL_cocoametalview *metalview
- = [[SDL_cocoametalview alloc] initWithFrame:view.frame
- useHighDPI:(window->flags & SDL_WINDOW_ALLOW_HIGHDPI)];
+ = [[SDL_cocoametalview alloc] initWithFrame:view.frame scale:scale];
[view addSubview:metalview];
return metalview;
}
@@ -119,6 +125,8 @@ Cocoa_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h)
if (h) {
*h = layer.drawableSize.height;
}
+ } else {
+ SDL_GetWindowSize(window, w, h);
}
}
diff --git a/src/video/uikit/SDL_uikitmetalview.h b/src/video/uikit/SDL_uikitmetalview.h
index 31fefd4..bc97778 100644
--- a/src/video/uikit/SDL_uikitmetalview.h
+++ b/src/video/uikit/SDL_uikitmetalview.h
@@ -43,8 +43,7 @@
@interface SDL_uikitmetalview : SDL_uikitview
- (instancetype)initWithFrame:(CGRect)frame
- scale:(CGFloat)scale
- tag:(int)tag;
+ scale:(CGFloat)scale;
@end
diff --git a/src/video/uikit/SDL_uikitmetalview.m b/src/video/uikit/SDL_uikitmetalview.m
index 4ee8b94..104189d 100644
--- a/src/video/uikit/SDL_uikitmetalview.m
+++ b/src/video/uikit/SDL_uikitmetalview.m
@@ -46,14 +46,12 @@
- (instancetype)initWithFrame:(CGRect)frame
scale:(CGFloat)scale
- tag:(int)tag
{
if ((self = [super initWithFrame:frame])) {
- /* Set the appropriate scale (for retina display support) */
- self.contentScaleFactor = scale;
- self.tag = tag;
-
- [self updateDrawableSize];
+ self.tag = METALVIEW_TAG;
+ /* Set the desired scale. The default drawableSize of a CAMetalLayer
+ * is its bounds x its scale so nothing further needs to be done. */
+ self.layer.contentsScale = scale;
}
return self;
@@ -63,16 +61,6 @@
- (void)layoutSubviews
{
[super layoutSubviews];
- [self updateDrawableSize];
-}
-
-- (void)updateDrawableSize
-{
- CGSize size = self.bounds.size;
- size.width *= self.contentScaleFactor;
- size.height *= self.contentScaleFactor;
-
- ((CAMetalLayer *) self.layer).drawableSize = size;
}
@end
@@ -89,9 +77,10 @@ UIKit_Mtl_AddMetalView(SDL_Window* window)
}
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
- /* Set the scale to the natural scale factor of the screen - the
- * backing dimensions of the Metal view will match the pixel
- * dimensions of the screen rather than the dimensions in points.
+ /* Set the scale to the natural scale factor of the screen - then
+ * the backing dimensions of the Metal view will match the pixel
+ * dimensions of the screen rather than the dimensions in points
+ * yielding high resolution on retine displays.
*/
#ifdef __IPHONE_8_0
if ([data.uiwindow.screen respondsToSelector:@selector(nativeScale)]) {
@@ -104,8 +93,7 @@ UIKit_Mtl_AddMetalView(SDL_Window* window)
}
SDL_uikitmetalview *metalview
= [[SDL_uikitmetalview alloc] initWithFrame:view.frame
- scale:scale
- tag:METALVIEW_TAG];
+ scale:scale];
[metalview setSDLWindow:window];
return metalview;