Leave the Metal view active on the window when recreating the Metal renderer Fixes https://github.com/libsdl-org/SDL/issues/5140 Also move the metal tag definition to SDL_syswm.h so it can be used by applications
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 183 184 185 186 187
diff --git a/include/SDL_syswm.h b/include/SDL_syswm.h
index 363400d..f7cd670 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 dc9e41e..e093fd4 100644
--- a/src/render/metal/SDL_render_metal.m
+++ b/src/render/metal/SDL_render_metal.m
@@ -32,6 +32,7 @@
#import <QuartzCore/CAMetalLayer.h>
#ifdef __MACOSX__
+#import <AppKit/NSWindow.h>
#import <AppKit/NSView.h>
#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 87f1d35..d8948b3 100644
--- a/src/video/cocoa/SDL_cocoametalview.h
+++ b/src/video/cocoa/SDL_cocoametalview.h
@@ -39,7 +39,6 @@
#import <Metal/Metal.h>
#import <QuartzCore/CAMetalLayer.h>
-#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 d73e2b3..6e33c48 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 1972a4a..91cd0b0 100644
--- a/src/video/uikit/SDL_uikitmetalview.h
+++ b/src/video/uikit/SDL_uikitmetalview.h
@@ -38,7 +38,6 @@
#import <Metal/Metal.h>
#import <QuartzCore/CAMetalLayer.h>
-#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 97bbe37..8274eaf 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);