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
This commit is contained in:
Sam Lantinga 2022-11-15 10:18:41 -08:00
parent a71ad40ac3
commit 70656b133c
5 changed files with 11 additions and 65 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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));

View file

@ -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)