diff --git a/include/SDL_syswm.h b/include/SDL_syswm.h index 363400d96..f7cd670cd 100644 --- a/include/SDL_syswm.h +++ b/include/SDL_syswm.h @@ -98,6 +98,10 @@ typedef struct _UIViewController UIViewController; typedef Uint32 GLuint; #endif +#if defined(SDL_VIDEO_VULKAN) || defined(SDL_VIDEO_METAL) +#define SDL_METALVIEW_TAG 255 +#endif + #if defined(SDL_VIDEO_DRIVER_ANDROID) typedef struct ANativeWindow ANativeWindow; typedef void *EGLSurface; diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m index dc9e41ec9..e093fd4d8 100644 --- a/src/render/metal/SDL_render_metal.m +++ b/src/render/metal/SDL_render_metal.m @@ -32,6 +32,7 @@ #import #ifdef __MACOSX__ +#import #import #endif @@ -1565,7 +1566,11 @@ METAL_DestroyRenderer(SDL_Renderer * renderer) DestroyAllPipelines(data.allpipelines, data.pipelinescount); - SDL_Metal_DestroyView(data.mtlview); + /* Release the metal view instead of destroying it, + in case we want to use it later (recreating the renderer) + */ + /* SDL_Metal_DestroyView(data.mtlview); */ + CFBridgingRelease(data.mtlview); } SDL_free(renderer); @@ -1608,6 +1613,33 @@ METAL_SetVSync(SDL_Renderer * renderer, const int vsync) return SDL_SetError("This Apple OS does not support displaySyncEnabled!"); } +static SDL_MetalView GetWindowView(SDL_Window *window) +{ + SDL_SysWMinfo info; + + SDL_VERSION(&info.version); + if (SDL_GetWindowWMInfo(window, &info)) { +#ifdef __MACOSX__ + if (info.subsystem == SDL_SYSWM_COCOA) { + NSView *view = info.info.cocoa.window.contentView; + if (view.subviews.count > 0) { + view = view.subviews[0]; + if (view.tag == SDL_METALVIEW_TAG) { + return (SDL_MetalView)CFBridgingRetain(view); + } + } + } +#else + if (info.subsystem == SDL_SYSWM_UIKIT) { + UIView *view = info.info.uikit.window.rootViewController.view; + if (view.tag == SDL_METALVIEW_TAG) { + return (SDL_MetalView)CFBridgingRetain(view); + } + } +#endif + } + return nil; +} static SDL_Renderer * METAL_CreateRenderer(SDL_Window * window, Uint32 flags) @@ -1659,7 +1691,10 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags) return NULL; } - view = SDL_Metal_CreateView(window); + view = GetWindowView(window); + if (view == nil) { + view = SDL_Metal_CreateView(window); + } if (view == NULL) { #if !__has_feature(objc_arc) @@ -1679,7 +1714,11 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags) #if !__has_feature(objc_arc) [mtldevice release]; #endif - SDL_Metal_DestroyView(view); + /* Release the metal view instead of destroying it, + in case we want to use it later (recreating the renderer) + */ + /* SDL_Metal_DestroyView(view); */ + CFBridgingRelease(view); SDL_free(renderer); if (changed_window) { SDL_RecreateWindow(window, window_flags); diff --git a/src/video/cocoa/SDL_cocoametalview.h b/src/video/cocoa/SDL_cocoametalview.h index 87f1d3555..d8948b3d6 100644 --- a/src/video/cocoa/SDL_cocoametalview.h +++ b/src/video/cocoa/SDL_cocoametalview.h @@ -39,7 +39,6 @@ #import #import -#define METALVIEW_TAG 255 @interface SDL_cocoametalview : NSView diff --git a/src/video/cocoa/SDL_cocoametalview.m b/src/video/cocoa/SDL_cocoametalview.m index d73e2b377..6e33c4899 100644 --- a/src/video/cocoa/SDL_cocoametalview.m +++ b/src/video/cocoa/SDL_cocoametalview.m @@ -31,6 +31,8 @@ #if SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL) #include "SDL_events.h" +#include "SDL_syswm.h" + static int SDLCALL SDL_MetalViewEventWatch(void *userdata, SDL_Event *event) @@ -103,7 +105,7 @@ SDL_MetalViewEventWatch(void *userdata, SDL_Event *event) - (NSInteger)tag { - return METALVIEW_TAG; + return SDL_METALVIEW_TAG; } - (void)updateDrawableSize @@ -173,7 +175,7 @@ Cocoa_Metal_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h) { @autoreleasepool { SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata; NSView *contentView = data->sdlContentView; - SDL_cocoametalview* metalview = [contentView viewWithTag:METALVIEW_TAG]; + SDL_cocoametalview* metalview = [contentView viewWithTag:SDL_METALVIEW_TAG]; if (metalview) { CAMetalLayer *layer = (CAMetalLayer*)metalview.layer; SDL_assert(layer != NULL); diff --git a/src/video/uikit/SDL_uikitmetalview.h b/src/video/uikit/SDL_uikitmetalview.h index 1972a4a57..91cd0b0a2 100644 --- a/src/video/uikit/SDL_uikitmetalview.h +++ b/src/video/uikit/SDL_uikitmetalview.h @@ -38,7 +38,6 @@ #import #import -#define METALVIEW_TAG 255 @interface SDL_uikitmetalview : SDL_uikitview diff --git a/src/video/uikit/SDL_uikitmetalview.m b/src/video/uikit/SDL_uikitmetalview.m index 97bbe37b6..8274eaff9 100644 --- a/src/video/uikit/SDL_uikitmetalview.m +++ b/src/video/uikit/SDL_uikitmetalview.m @@ -30,7 +30,9 @@ #if SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL) -#import "../SDL_sysvideo.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" + #import "SDL_uikitwindow.h" #import "SDL_uikitmetalview.h" @@ -47,7 +49,7 @@ scale:(CGFloat)scale { if ((self = [super initWithFrame:frame])) { - self.tag = METALVIEW_TAG; + self.tag = SDL_METALVIEW_TAG; self.layer.contentsScale = scale; [self updateDrawableSize]; } @@ -122,7 +124,7 @@ UIKit_Metal_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h) @autoreleasepool { SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata; SDL_uikitview *view = (SDL_uikitview*)data.uiwindow.rootViewController.view; - SDL_uikitmetalview* metalview = [view viewWithTag:METALVIEW_TAG]; + SDL_uikitmetalview* metalview = [view viewWithTag:SDL_METALVIEW_TAG]; if (metalview) { CAMetalLayer *layer = (CAMetalLayer*)metalview.layer; assert(layer != NULL);