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
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
diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m
index 3dc346d..80fd96f 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<MTLCommandQueue> 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 51e282f..c75b026 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 af6eb0c..8bc3380 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 5369bb2..dcd63c7 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 50d7393..8c48cfa 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)