mirror of
				https://github.com/libsdl-org/SDL.git
				synced 2025-10-26 12:27:44 +00:00 
			
		
		
		
	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.
This commit is contained in:
		| @@ -110,7 +110,9 @@ typedef enum | |||||||
|     SDL_WINDOW_MOUSE_FOCUS = 0x00000400,        /**< window has mouse focus */ |     SDL_WINDOW_MOUSE_FOCUS = 0x00000400,        /**< window has mouse focus */ | ||||||
|     SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ), |     SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ), | ||||||
|     SDL_WINDOW_FOREIGN = 0x00000800,            /**< window not created by SDL */ |     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_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_ALWAYS_ON_TOP = 0x00008000,      /**< window should always be above others */ | ||||||
|     SDL_WINDOW_SKIP_TASKBAR  = 0x00010000,      /**< window should not be added to the taskbar */ |     SDL_WINDOW_SKIP_TASKBAR  = 0x00010000,      /**< window should not be added to the taskbar */ | ||||||
|   | |||||||
| @@ -240,6 +240,9 @@ extern DECLSPEC SDL_bool SDLCALL SDL_Vulkan_CreateSurface( | |||||||
|  * platform with high-DPI support (Apple calls this "Retina"), and not disabled |  * platform with high-DPI support (Apple calls this "Retina"), and not disabled | ||||||
|  * by the \c SDL_HINT_VIDEO_HIGHDPI_DISABLED hint. |  * 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_GetWindowSize() | ||||||
|  *  \sa SDL_CreateWindow() |  *  \sa SDL_CreateWindow() | ||||||
|  */ |  */ | ||||||
|   | |||||||
| @@ -41,11 +41,10 @@ | |||||||
|  |  | ||||||
| @interface SDL_cocoametalview : NSView { | @interface SDL_cocoametalview : NSView { | ||||||
|     NSInteger _tag; |     NSInteger _tag; | ||||||
|     bool _useHighDPI; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| - (instancetype)initWithFrame:(NSRect)frame | - (instancetype)initWithFrame:(NSRect)frame | ||||||
|                    useHighDPI:(bool)useHighDPI; |                         scale:(CGFloat)scale; | ||||||
|  |  | ||||||
| /* Override superclass tag so this class can set it. */ | /* Override superclass tag so this class can set it. */ | ||||||
| @property (assign, readonly) NSInteger tag; | @property (assign, readonly) NSInteger tag; | ||||||
|   | |||||||
| @@ -57,17 +57,19 @@ | |||||||
| } | } | ||||||
|  |  | ||||||
| - (instancetype)initWithFrame:(NSRect)frame | - (instancetype)initWithFrame:(NSRect)frame | ||||||
|                    useHighDPI:(bool)useHighDPI |                         scale:(CGFloat)scale | ||||||
| { | { | ||||||
| 	if ((self = [super initWithFrame:frame])) { | 	if ((self = [super initWithFrame:frame])) { | ||||||
|  |         _tag = METALVIEW_TAG; | ||||||
|         self.wantsLayer = YES; |         self.wantsLayer = YES; | ||||||
|  |  | ||||||
|         /* Allow resize. */ |         /* Allow resize. */ | ||||||
|         self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; |         self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; | ||||||
|         _tag = METALVIEW_TAG; |  | ||||||
|  |  | ||||||
|         _useHighDPI = useHighDPI; |         /* Set the desired scale. The default drawableSize of a CAMetalLayer | ||||||
|         [self updateDrawableSize]; |          * is its bounds x its scale so nothing further needs to be done. | ||||||
|  |          */ | ||||||
|  |         self.layer.contentsScale = scale; | ||||||
| 	} | 	} | ||||||
|    |    | ||||||
| 	return self; | 	return self; | ||||||
| @@ -77,16 +79,6 @@ | |||||||
| - (void)resizeWithOldSuperviewSize:(NSSize)oldSize | - (void)resizeWithOldSuperviewSize:(NSSize)oldSize | ||||||
| { | { | ||||||
|     [super resizeWithOldSuperviewSize: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 | @end | ||||||
| @@ -94,12 +86,26 @@ | |||||||
| SDL_cocoametalview* | SDL_cocoametalview* | ||||||
| Cocoa_Mtl_AddMetalView(SDL_Window* window) | 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; |     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 *metalview | ||||||
|         = [[SDL_cocoametalview alloc] initWithFrame:view.frame |         = [[SDL_cocoametalview alloc] initWithFrame:view.frame scale:scale]; | ||||||
|                        useHighDPI:(window->flags & SDL_WINDOW_ALLOW_HIGHDPI)]; |  | ||||||
|     [view addSubview:metalview]; |     [view addSubview:metalview]; | ||||||
|     return metalview; |     return metalview; | ||||||
| } | } | ||||||
| @@ -119,6 +125,8 @@ Cocoa_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h) | |||||||
|         if (h) { |         if (h) { | ||||||
|             *h = layer.drawableSize.height; |             *h = layer.drawableSize.height; | ||||||
|         } |         } | ||||||
|  |     } else { | ||||||
|  |         SDL_GetWindowSize(window, w, h); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -43,8 +43,7 @@ | |||||||
| @interface SDL_uikitmetalview : SDL_uikitview | @interface SDL_uikitmetalview : SDL_uikitview | ||||||
|  |  | ||||||
| - (instancetype)initWithFrame:(CGRect)frame | - (instancetype)initWithFrame:(CGRect)frame | ||||||
|                         scale:(CGFloat)scale |                         scale:(CGFloat)scale; | ||||||
|                         tag:(int)tag; |  | ||||||
|  |  | ||||||
| @end | @end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -46,14 +46,12 @@ | |||||||
|  |  | ||||||
| - (instancetype)initWithFrame:(CGRect)frame | - (instancetype)initWithFrame:(CGRect)frame | ||||||
|                         scale:(CGFloat)scale |                         scale:(CGFloat)scale | ||||||
|                           tag:(int)tag |  | ||||||
| { | { | ||||||
|     if ((self = [super initWithFrame:frame])) { |     if ((self = [super initWithFrame:frame])) { | ||||||
|         /* Set the appropriate scale (for retina display support) */ |         self.tag = METALVIEW_TAG; | ||||||
|         self.contentScaleFactor = scale; |         /* Set the desired scale. The default drawableSize of a CAMetalLayer | ||||||
|         self.tag = tag; |          * is its bounds x its scale so nothing further needs to be done. */ | ||||||
|  |         self.layer.contentsScale = scale; | ||||||
|         [self updateDrawableSize]; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return self; |     return self; | ||||||
| @@ -63,16 +61,6 @@ | |||||||
| - (void)layoutSubviews | - (void)layoutSubviews | ||||||
| { | { | ||||||
|     [super 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 | @end | ||||||
| @@ -89,9 +77,10 @@ UIKit_Mtl_AddMetalView(SDL_Window* window) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
|     if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) { |     if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) { | ||||||
|         /* Set the scale to the natural scale factor of the screen - the |         /* Set the scale to the natural scale factor of the screen - then | ||||||
|          * backing dimensions of the Metal view will match the pixel |          * the backing dimensions of the Metal view will match the pixel | ||||||
|          * dimensions of the screen rather than the dimensions in points. |          * dimensions of the screen rather than the dimensions in points | ||||||
|  |          * yielding high resolution on retine displays. | ||||||
|          */ |          */ | ||||||
| #ifdef __IPHONE_8_0 | #ifdef __IPHONE_8_0 | ||||||
|         if ([data.uiwindow.screen respondsToSelector:@selector(nativeScale)]) { |         if ([data.uiwindow.screen respondsToSelector:@selector(nativeScale)]) { | ||||||
| @@ -104,8 +93,7 @@ UIKit_Mtl_AddMetalView(SDL_Window* window) | |||||||
|     } |     } | ||||||
|     SDL_uikitmetalview *metalview |     SDL_uikitmetalview *metalview | ||||||
|          = [[SDL_uikitmetalview alloc] initWithFrame:view.frame |          = [[SDL_uikitmetalview alloc] initWithFrame:view.frame | ||||||
|                                           scale:scale |                                                scale:scale]; | ||||||
|                                             tag:METALVIEW_TAG]; |  | ||||||
|     [metalview setSDLWindow:window]; |     [metalview setSDLWindow:window]; | ||||||
|  |  | ||||||
|     return metalview; |     return metalview; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Mark Callow
					Mark Callow