From 70656b133c89c614422130b6c7e0a52cdccc6d4f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 15 Nov 2022 10:18:41 -0800 Subject: [PATCH] Don't recreate the window when creating a Metal renderer on an OpenGL window. It turns out that we can safely create a Metal view on an existing window, and that avoids issues with the window being recreated with the wrong orientation in iOS 16. Fixes https://github.com/libsdl-org/SDL/issues/6289 --- src/render/metal/SDL_render_metal.m | 25 ------------------------- src/video/SDL_video.c | 12 ++++++++++-- src/video/uikit/SDL_uikitmetalview.m | 12 ------------ src/video/uikit/SDL_uikitview.h | 2 -- src/video/uikit/SDL_uikitview.m | 25 +------------------------ 5 files changed, 11 insertions(+), 65 deletions(-) diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m index 3dc346d57..80fd96f07 100644 --- a/src/render/metal/SDL_render_metal.m +++ b/src/render/metal/SDL_render_metal.m @@ -55,9 +55,6 @@ /* Apple Metal renderer implementation */ -/* Used to re-create the window with Metal capability */ -extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags); - /* macOS requires constants in a buffer to have a 256 byte alignment. */ /* Use native type alignments from https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf */ #if defined(__MACOSX__) || TARGET_OS_SIMULATOR || TARGET_OS_MACCATALYST @@ -1635,13 +1632,11 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags) SDL_MetalView view = NULL; CAMetalLayer *layer = nil; SDL_SysWMinfo syswm; - SDL_bool changed_window = SDL_FALSE; NSError *err = nil; dispatch_data_t mtllibdata; char *constantdata; int maxtexsize, quadcount = UINT16_MAX / 4; UInt16 *indexdata; - Uint32 window_flags; size_t indicessize = sizeof(UInt16) * quadcount * 6; MTLSamplerDescriptor *samplerdesc; id mtlcmdqueue; @@ -1697,20 +1692,9 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags) return NULL; } - window_flags = SDL_GetWindowFlags(window); - if (!(window_flags & SDL_WINDOW_METAL)) { - changed_window = SDL_TRUE; - if (SDL_RecreateWindow(window, (window_flags & ~(SDL_WINDOW_VULKAN | SDL_WINDOW_OPENGL)) | SDL_WINDOW_METAL) < 0) { - return NULL; - } - } - renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); if (!renderer) { SDL_OutOfMemory(); - if (changed_window) { - SDL_RecreateWindow(window, window_flags); - } return NULL; } @@ -1720,9 +1704,6 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags) if (mtldevice == nil) { SDL_free(renderer); SDL_SetError("Failed to obtain Metal device"); - if (changed_window) { - SDL_RecreateWindow(window, window_flags); - } return NULL; } @@ -1733,9 +1714,6 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags) if (view == NULL) { SDL_free(renderer); - if (changed_window) { - SDL_RecreateWindow(window, window_flags); - } return NULL; } @@ -1749,9 +1727,6 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags) /* SDL_Metal_DestroyView(view); */ CFBridgingRelease(view); SDL_free(renderer); - if (changed_window) { - SDL_RecreateWindow(window, window_flags); - } return NULL; } diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 51e282f06..c75b026d9 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -4853,8 +4853,16 @@ SDL_Metal_CreateView(SDL_Window * window) CHECK_WINDOW_MAGIC(window, NULL); if (!(window->flags & SDL_WINDOW_METAL)) { - SDL_SetError("The specified window isn't a Metal window"); - return NULL; + /* No problem, we can convert to Metal */ + if (window->flags & SDL_WINDOW_OPENGL) { + window->flags &= ~SDL_WINDOW_OPENGL; + SDL_GL_UnloadLibrary(); + } + if (window->flags & SDL_WINDOW_VULKAN) { + window->flags &= ~SDL_WINDOW_VULKAN; + SDL_Vulkan_UnloadLibrary(); + } + window->flags |= SDL_WINDOW_METAL; } return _this->Metal_CreateView(_this, window); diff --git a/src/video/uikit/SDL_uikitmetalview.m b/src/video/uikit/SDL_uikitmetalview.m index af6eb0cd3..8bc338095 100644 --- a/src/video/uikit/SDL_uikitmetalview.m +++ b/src/video/uikit/SDL_uikitmetalview.m @@ -69,18 +69,6 @@ CGSize size = self.bounds.size; size.width *= self.layer.contentsScale; size.height *= self.layer.contentsScale; - - /* Make sure the width/height are oriented correctly - * - * This works around an issue in iOS 16 where the bounds come back in portrait mode - * instead of landscape until the event loop runs. - */ - if ([self shouldSwapDimensions:(size.width >= size.height)]) { - CGFloat temp = size.width; - size.width = size.height; - size.height = temp; - } - ((CAMetalLayer *)self.layer).drawableSize = size; } diff --git a/src/video/uikit/SDL_uikitview.h b/src/video/uikit/SDL_uikitview.h index 5369bb212..dcd63c7a5 100644 --- a/src/video/uikit/SDL_uikitview.h +++ b/src/video/uikit/SDL_uikitview.h @@ -35,8 +35,6 @@ - (void)setSDLWindow:(SDL_Window *)window; -- (BOOL)shouldSwapDimensions:(BOOL)portrait; - #if !TARGET_OS_TV && defined(__IPHONE_13_4) - (UIPointerRegion *)pointerInteraction:(UIPointerInteraction *)interaction regionForRequest:(UIPointerRegionRequest *)request defaultRegion:(UIPointerRegion *)defaultRegion API_AVAILABLE(ios(13.4)); - (UIPointerStyle *)pointerInteraction:(UIPointerInteraction *)interaction styleForRegion:(UIPointerRegion *)region API_AVAILABLE(ios(13.4)); diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index 50d7393e7..8c48cfa50 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -120,8 +120,6 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick; [data.uiwindow layoutIfNeeded]; } - sdlwindow = window; - /* Add ourself to the new window. */ if (window) { data = (__bridge SDL_WindowData *) window->driverdata; @@ -146,29 +144,8 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick; * layout now to immediately update the bounds. */ [data.uiwindow layoutIfNeeded]; } -} -- (BOOL)shouldSwapDimensions:(BOOL)landscape -{ -#if !TARGET_OS_TV - if (sdlwindow) { - SDL_VideoDisplay *display = SDL_GetDisplayForWindow(sdlwindow); - SDL_DisplayData *displaydata = (__bridge SDL_DisplayData *) display->driverdata; - - if (displaydata.uiscreen == [UIScreen mainScreen]) { - NSUInteger orients = UIKit_GetSupportedOrientations(sdlwindow); - BOOL supportsLandscape = (orients & UIInterfaceOrientationMaskLandscape) != 0; - BOOL supportsPortrait = (orients & (UIInterfaceOrientationMaskPortrait|UIInterfaceOrientationMaskPortraitUpsideDown)) != 0; - - /* Make sure the width/height are oriented correctly */ - if ((landscape && !supportsLandscape) || (!landscape && !supportsPortrait)) { - return YES; - } - } - } -#endif /* !TARGET_OS_TV */ - - return NO; + sdlwindow = window; } #if !TARGET_OS_TV && defined(__IPHONE_13_4)