Add public APIs for creating a Metal view attached to an SDL window. Add SDL_metal.h.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6e36a84..a4ed541 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -373,8 +373,10 @@
 set_option(DIRECTX             "Use DirectX for Windows audio/video" ${WINDOWS})
 set_option(WASAPI              "Use the Windows WASAPI audio driver" ${WINDOWS})
 set_option(RENDER_D3D          "Enable the Direct3D render driver" ${WINDOWS})
+set_option(RENDER_METAL        "Enable the Metal render driver" ${APPLE})
 set_option(VIDEO_VIVANTE       "Use Vivante EGL video driver" ${UNIX_SYS})
 dep_option(VIDEO_VULKAN        "Enable Vulkan support" ON "ANDROID OR APPLE OR LINUX OR WINDOWS" OFF)
+set_option(VIDEO_METAL         "Enable Metal support" ${APPLE})
 set_option(VIDEO_KMSDRM        "Use KMS DRM video driver" ${UNIX_SYS})
 dep_option(KMSDRM_SHARED       "Dynamically load KMS DRM support" ON "VIDEO_KMSDRM" OFF)
 option_string(BACKGROUNDING_SIGNAL "number to use for magic backgrounding signal or 'OFF'" "OFF")
@@ -1533,6 +1535,69 @@
     set(HAVE_SDL_FILESYSTEM TRUE)
   endif()
 
+  # iOS hack needed - http://code.google.com/p/ios-cmake/ ?
+  if(SDL_VIDEO)
+    if (IOS)
+      set(SDL_VIDEO_DRIVER_UIKIT 1)
+      file(GLOB UIKITVIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/uikit/*.m)
+      set(SOURCE_FILES ${SOURCE_FILES} ${UIKITVIDEO_SOURCES})
+    else()
+      CheckCOCOA()
+      if(VIDEO_OPENGL)
+        set(SDL_VIDEO_OPENGL 1)
+        set(SDL_VIDEO_OPENGL_CGL 1)
+        set(SDL_VIDEO_RENDER_OGL 1)
+        set(HAVE_VIDEO_OPENGL TRUE)
+      endif()
+
+      if(VIDEO_OPENGLES)
+        set(SDL_VIDEO_OPENGL_EGL 1)
+        set(SDL_VIDEO_OPENGL_ES2 1)
+        set(SDL_VIDEO_RENDER_OGL_ES2 1)
+        set(HAVE_VIDEO_OPENGLES TRUE)
+      endif()
+    endif()
+    
+    if(VIDEO_VULKAN OR VIDEO_METAL OR RENDER_METAL)
+      set(ORIG_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
+      set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -x objective-c")
+      check_c_source_compiles("
+        #include <AvailabilityMacros.h>
+        #import <Metal/Metal.h>
+        #import <QuartzCore/CAMetalLayer.h>
+
+        #if TARGET_OS_SIMULATOR || (!TARGET_CPU_X86_64 && !TARGET_CPU_ARM64)
+        #error Metal doesn't work on this configuration
+        #endif
+        int main()
+        {
+            return 0;
+        }
+        " HAVE_FRAMEWORK_METAL)
+      set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
+      if(HAVE_FRAMEWORK_METAL)
+        set(SDL_FRAMEWORK_METAL 1)
+        set(SDL_FRAMEWORK_QUARTZCORE 1)
+      else()
+        set(VIDEO_VULKAN 0)
+        set(VIDEO_METAL 0)
+        set(RENDER_METAL 0)
+      endif()
+    endif()
+
+    if(VIDEO_METAL)
+      set(SDL_VIDEO_METAL 1)
+      set(HAVE_VIDEO_METAL TRUE)
+    endif()
+
+    if(RENDER_METAL)
+      file(GLOB RENDER_METAL_SOURCES ${SDL2_SOURCE_DIR}/src/render/metal/*.m)
+      set(SOURCE_FILES ${SOURCE_FILES} ${RENDER_METAL_SOURCES})
+      set(SDL_VIDEO_RENDER_METAL 1)
+      set(HAVE_RENDER_METAL TRUE)
+    endif()
+  endif()
+
   # Actually load the frameworks at the end so we don't duplicate include.
   if(SDL_FRAMEWORK_COREVIDEO)
     find_library(COREVIDEO CoreVideo)
@@ -1562,28 +1627,20 @@
     find_library(AUDIOTOOLBOX AudioToolbox)
     list(APPEND EXTRA_LIBS ${AUDIOTOOLBOX})
   endif()
-
-  # iOS hack needed - http://code.google.com/p/ios-cmake/ ?
-  if(SDL_VIDEO)
-    if (IOS)
-      set(SDL_VIDEO_DRIVER_UIKIT 1)
-      file(GLOB UIKITVIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/uikit/*.m)
-      set(SOURCE_FILES ${SOURCE_FILES} ${UIKITVIDEO_SOURCES})
+  if(SDL_FRAMEWORK_METAL)
+    if(IOS)
+      find_library(METAL Metal)
+      list(APPEND EXTRA_LIBS ${METAL})
     else()
-      CheckCOCOA()
-      if(VIDEO_OPENGL)
-        set(SDL_VIDEO_OPENGL 1)
-        set(SDL_VIDEO_OPENGL_CGL 1)
-        set(SDL_VIDEO_RENDER_OGL 1)
-        set(HAVE_VIDEO_OPENGL TRUE)
-      endif()
-
-      if(VIDEO_OPENGLES)
-        set(SDL_VIDEO_OPENGL_EGL 1)
-        set(SDL_VIDEO_OPENGL_ES2 1)
-        set(SDL_VIDEO_RENDER_OGL_ES2 1)
-        set(HAVE_VIDEO_OPENGLES TRUE)
-      endif()
+      list(APPEND EXTRA_LDFLAGS "-Wl,-weak_framework,Metal")
+    endif()
+  endif()
+  if(SDL_FRAMEWORK_QUARTZCORE)
+    if(IOS)
+      find_library(QUARTZCORE QuartzCore)
+      list(APPEND EXTRA_LIBS ${QUARTZCORE})
+    else()
+      list(APPEND EXTRA_LDFLAGS "-Wl,-weak_framework,QuartzCore")
     endif()
   endif()
 
diff --git a/Makefile.in b/Makefile.in
index 567624e..6b4eecf 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -84,6 +84,7 @@
 	SDL_log.h \
 	SDL_main.h \
 	SDL_messagebox.h \
+	SDL_metal.h \
 	SDL_mouse.h \
 	SDL_mutex.h \
 	SDL_name.h \
diff --git a/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj b/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj
index ef8539b..3146cb3 100644
--- a/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj
+++ b/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj
@@ -717,6 +717,7 @@
 		F3E3C75B224138AE007D243C /* SDL_uikit_main.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E3C657224069CE007D243C /* SDL_uikit_main.c */; };
 		FA1DC2721C62BE65008F99A0 /* SDL_uikitclipboard.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1DC2701C62BE65008F99A0 /* SDL_uikitclipboard.h */; };
 		FA1DC2731C62BE65008F99A0 /* SDL_uikitclipboard.m in Sources */ = {isa = PBXBuildFile; fileRef = FA1DC2711C62BE65008F99A0 /* SDL_uikitclipboard.m */; };
+		FA24348D21D4201400B8918A /* SDL_metal.h in Headers */ = {isa = PBXBuildFile; fileRef = FA24348C21D4201400B8918A /* SDL_metal.h */; };
 		FAB5981D1BB5C31500BE72C5 /* SDL_atomic.c in Sources */ = {isa = PBXBuildFile; fileRef = 04FFAB8912E23B8D00BA343D /* SDL_atomic.c */; };
 		FAB5981E1BB5C31500BE72C5 /* SDL_spinlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 04FFAB8A12E23B8D00BA343D /* SDL_spinlock.c */; };
 		FAB5981F1BB5C31500BE72C5 /* SDL_coreaudio.m in Sources */ = {isa = PBXBuildFile; fileRef = 56EA86F913E9EC2B002E47EB /* SDL_coreaudio.m */; };
@@ -1064,6 +1065,7 @@
 		F3E3C75F224138AE007D243C /* libSDLmain.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSDLmain.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		FA1DC2701C62BE65008F99A0 /* SDL_uikitclipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitclipboard.h; sourceTree = "<group>"; };
 		FA1DC2711C62BE65008F99A0 /* SDL_uikitclipboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_uikitclipboard.m; sourceTree = "<group>"; };
+		FA24348C21D4201400B8918A /* SDL_metal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_metal.h; sourceTree = "<group>"; };
 		FAB598141BB5C1B100BE72C5 /* libSDL2.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSDL2.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		FAD4F7011BA3C4E8008346CE /* SDL_sysjoystick_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysjoystick_c.h; sourceTree = "<group>"; };
 		FD0BBFEF0E3933DD00D833B1 /* SDL_uikitview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitview.h; sourceTree = "<group>"; };
@@ -1576,15 +1578,14 @@
 			children = (
 				AA7558651595D55500BBD41B /* begin_code.h */,
 				AA7558661595D55500BBD41B /* close_code.h */,
-				AA7558971595D55500BBD41B /* SDL.h */,
 				AA7558671595D55500BBD41B /* SDL_assert.h */,
 				AA7558681595D55500BBD41B /* SDL_atomic.h */,
 				AA7558691595D55500BBD41B /* SDL_audio.h */,
 				AADA5B8E16CCAB7C00107CF7 /* SDL_bits.h */,
 				AA75586A1595D55500BBD41B /* SDL_blendmode.h */,
 				AA75586B1595D55500BBD41B /* SDL_clipboard.h */,
-				AA75586D1595D55500BBD41B /* SDL_config.h */,
 				AA75586C1595D55500BBD41B /* SDL_config_iphoneos.h */,
+				AA75586D1595D55500BBD41B /* SDL_config.h */,
 				AA75586E1595D55500BBD41B /* SDL_copying.h */,
 				AA75586F1595D55500BBD41B /* SDL_cpuinfo.h */,
 				AA7558701595D55500BBD41B /* SDL_endian.h */,
@@ -1602,6 +1603,7 @@
 				AA75587B1595D55500BBD41B /* SDL_log.h */,
 				AA75587C1595D55500BBD41B /* SDL_main.h */,
 				AA9FF9501637C6E5000DF050 /* SDL_messagebox.h */,
+				FA24348C21D4201400B8918A /* SDL_metal.h */,
 				AA75587D1595D55500BBD41B /* SDL_mouse.h */,
 				AA75587E1595D55500BBD41B /* SDL_mutex.h */,
 				AA75587F1595D55500BBD41B /* SDL_name.h */,
@@ -1630,6 +1632,7 @@
 				AA7558951595D55500BBD41B /* SDL_version.h */,
 				AA7558961595D55500BBD41B /* SDL_video.h */,
 				4D7516FE1EE1C5B400820EEA /* SDL_vulkan.h */,
+				AA7558971595D55500BBD41B /* SDL.h */,
 			);
 			name = "Public Headers";
 			path = ../../include;
@@ -2183,6 +2186,7 @@
 				AA75589D1595D55500BBD41B /* SDL_blendmode.h in Headers */,
 				F30D9C9E212CD0990047DF2E /* SDL_sensor_c.h in Headers */,
 				AA75589E1595D55500BBD41B /* SDL_clipboard.h in Headers */,
+				FA24348D21D4201400B8918A /* SDL_metal.h in Headers */,
 				AA75589F1595D55500BBD41B /* SDL_config_iphoneos.h in Headers */,
 				AA7558A01595D55500BBD41B /* SDL_config.h in Headers */,
 				AA7558A11595D55500BBD41B /* SDL_copying.h in Headers */,
diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj
index 59c86f2..52f1389 100644
--- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj
+++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj
@@ -919,6 +919,7 @@
 		F3950CD8212BC88D00F51292 /* SDL_sensor.h in Headers */ = {isa = PBXBuildFile; fileRef = F3950CD7212BC88D00F51292 /* SDL_sensor.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		F3950CD9212BC88D00F51292 /* SDL_sensor.h in Headers */ = {isa = PBXBuildFile; fileRef = F3950CD7212BC88D00F51292 /* SDL_sensor.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		F3950CDA212BC88D00F51292 /* SDL_sensor.h in Headers */ = {isa = PBXBuildFile; fileRef = F3950CD7212BC88D00F51292 /* SDL_sensor.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FA24348B21D41FFB00B8918A /* SDL_metal.h in Headers */ = {isa = PBXBuildFile; fileRef = FA24348A21D41FFB00B8918A /* SDL_metal.h */; };
 		FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
 		FA73671E19A54140004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
 		FA73671F19A54144004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
@@ -1252,6 +1253,7 @@
 		F59C710300D5CB5801000001 /* ReadMe.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = ReadMe.txt; sourceTree = "<group>"; };
 		F59C710600D5CB5801000001 /* SDL.info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SDL.info; sourceTree = "<group>"; };
 		F5A2EF3900C6A39A01000001 /* BUGS.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = BUGS.txt; path = ../../BUGS.txt; sourceTree = SOURCE_ROOT; };
+		FA24348A21D41FFB00B8918A /* SDL_metal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_metal.h; sourceTree = "<group>"; };
 		FA73671C19A540EF004122E4 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; };
 		FABA34C61D8B5DB100915323 /* SDL_coreaudio.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_coreaudio.m; sourceTree = "<group>"; };
 /* End PBXFileReference section */
@@ -1342,6 +1344,7 @@
 				AA7557DD1595D4D800BBD41B /* SDL_log.h */,
 				AA7557DE1595D4D800BBD41B /* SDL_main.h */,
 				AA9FF9591637CBF9000DF050 /* SDL_messagebox.h */,
+				FA24348A21D41FFB00B8918A /* SDL_metal.h */,
 				AA7557DF1595D4D800BBD41B /* SDL_mouse.h */,
 				AA7557E01595D4D800BBD41B /* SDL_mutex.h */,
 				AA7557E11595D4D800BBD41B /* SDL_name.h */,
@@ -2029,6 +2032,7 @@
 				AA75580E1595D4D800BBD41B /* SDL_cpuinfo.h in Headers */,
 				AA7558101595D4D800BBD41B /* SDL_endian.h in Headers */,
 				AA7558121595D4D800BBD41B /* SDL_error.h in Headers */,
+				FA24348B21D41FFB00B8918A /* SDL_metal.h in Headers */,
 				AA7558141595D4D800BBD41B /* SDL_events.h in Headers */,
 				567E2F2117C44C35005F1892 /* SDL_filesystem.h in Headers */,
 				A77E6EB4167AB0A90010E40B /* SDL_gamecontroller.h in Headers */,
diff --git a/configure b/configure
index 8e0cefb..cfd6078 100755
--- a/configure
+++ b/configure
@@ -869,6 +869,7 @@
 enable_video_x11_vm
 enable_video_vivante
 enable_video_cocoa
+enable_video_metal
 enable_render_metal
 enable_video_directfb
 enable_directfb_shared
@@ -1647,6 +1648,7 @@
   --enable-video-x11-vm   use X11 VM extension for fullscreen [[default=yes]]
   --enable-video-vivante  use Vivante EGL video driver [[default=yes]]
   --enable-video-cocoa    use Cocoa video driver [[default=yes]]
+  --enable-video-metal    include Metal support [[default=yes]]
   --enable-render-metal   enable the Metal render driver [[default=yes]]
   --enable-video-directfb use DirectFB video driver [[default=no]]
   --enable-directfb-shared
@@ -21530,6 +21532,13 @@
 
 CheckMETAL()
 {
+    # Check whether --enable-video-metal was given.
+if test "${enable_video_metal+set}" = set; then :
+  enableval=$enable_video_metal;
+else
+  enable_video_metal=yes
+fi
+
     # Check whether --enable-render-metal was given.
 if test "${enable_render_metal+set}" = set; then :
   enableval=$enable_render_metal;
@@ -21537,7 +21546,7 @@
   enable_render_metal=yes
 fi
 
-    if test x$enable_render = xyes -a x$enable_render_metal = xyes; then
+    if test x$enable_video = xyes -a x$enable_video_metal = xyes; then
         save_CFLAGS="$CFLAGS"
                 CFLAGS="$CFLAGS -x objective-c"
         { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Metal framework" >&5
@@ -21574,11 +21583,17 @@
 $as_echo "$have_metal" >&6; }
         if test x$have_metal = xyes; then
 
+$as_echo "#define SDL_VIDEO_METAL 1" >>confdefs.h
+
+            if test x$enable_render = xyes -a x$enable_render_metal = xyes; then
+
 $as_echo "#define SDL_VIDEO_RENDER_METAL 1" >>confdefs.h
 
-            SOURCES="$SOURCES $srcdir/src/render/metal/*.m"
+                SOURCES="$SOURCES $srcdir/src/render/metal/*.m"
+            fi
             SUMMARY_video="${SUMMARY_video} metal"
         else
+            enable_video_metal=no
             enable_render_metal=no
         fi
     fi
@@ -25064,7 +25079,7 @@
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,QuartzCore"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,UIKit"
 
-        if test x$enable_render = xyes -a x$enable_render_metal = xyes; then
+        if test x$enable_video_metal = xyes -o x$enable_video_vulkan = xyes; then
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Metal"
         fi
         ;;
@@ -25158,7 +25173,7 @@
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,IOKit"
 
-        if test x$enable_render = xyes -a x$enable_render_metal = xyes; then
+        if test x$enable_video_metal = xyes -o x$enable_video_vulkan = xyes; then
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal"
         fi
         ;;
diff --git a/configure.ac b/configure.ac
index c6fd37f..62145ac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2048,10 +2048,13 @@
 
 CheckMETAL()
 {
+    AC_ARG_ENABLE(video-metal,
+AC_HELP_STRING([--enable-video-metal], [include Metal support [[default=yes]]]),
+              , enable_video_metal=yes)
     AC_ARG_ENABLE(render-metal,
 AS_HELP_STRING([--enable-render-metal], [enable the Metal render driver [[default=yes]]]),
                                 , enable_render_metal=yes)
-    if test x$enable_render = xyes -a x$enable_render_metal = xyes; then
+    if test x$enable_video = xyes -a x$enable_video_metal = xyes; then
         save_CFLAGS="$CFLAGS"
         dnl Work around that we don't have Objective-C support in autoconf
         CFLAGS="$CFLAGS -x objective-c"
@@ -2072,10 +2075,14 @@
         CFLAGS="$save_CFLAGS"
         AC_MSG_RESULT($have_metal)
         if test x$have_metal = xyes; then
-            AC_DEFINE(SDL_VIDEO_RENDER_METAL, 1, [ ])
-            SOURCES="$SOURCES $srcdir/src/render/metal/*.m"
+            AC_DEFINE(SDL_VIDEO_METAL, 1, [ ])
+            if test x$enable_render = xyes -a x$enable_render_metal = xyes; then
+                AC_DEFINE(SDL_VIDEO_RENDER_METAL, 1, [ ])
+                SOURCES="$SOURCES $srcdir/src/render/metal/*.m"
+            fi
             SUMMARY_video="${SUMMARY_video} metal"
         else
+            enable_video_metal=no
             enable_render_metal=no
         fi
     fi
@@ -3828,7 +3835,7 @@
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,QuartzCore"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,UIKit"
 
-        if test x$enable_render = xyes -a x$enable_render_metal = xyes; then
+        if test x$enable_video_metal = xyes -o x$enable_video_vulkan = xyes; then
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Metal"
         fi
         ;;
@@ -3910,7 +3917,7 @@
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,IOKit"
 
-        if test x$enable_render = xyes -a x$enable_render_metal = xyes; then
+        if test x$enable_video_metal = xyes -o x$enable_video_vulkan = xyes; then
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal"
         fi
         ;;
diff --git a/include/SDL.h b/include/SDL.h
index 88dce0c..e432939 100644
--- a/include/SDL.h
+++ b/include/SDL.h
@@ -47,6 +47,7 @@
 #include "SDL_loadso.h"
 #include "SDL_log.h"
 #include "SDL_messagebox.h"
+#include "SDL_metal.h"
 #include "SDL_mutex.h"
 #include "SDL_power.h"
 #include "SDL_render.h"
diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake
index 75ff0bb..65ba3ea 100644
--- a/include/SDL_config.h.cmake
+++ b/include/SDL_config.h.cmake
@@ -388,6 +388,9 @@
 /* Enable Vulkan support */
 #cmakedefine SDL_VIDEO_VULKAN @SDL_VIDEO_VULKAN@
 
+/* Enable Metal support */
+#cmakedefine SDL_VIDEO_METAL @SDL_VIDEO_METAL@
+
 /* Enable system power support */
 #cmakedefine SDL_POWER_ANDROID @SDL_POWER_ANDROID@
 #cmakedefine SDL_POWER_LINUX @SDL_POWER_LINUX@
diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in
index e4eb6f6..6d5d13e 100644
--- a/include/SDL_config.h.in
+++ b/include/SDL_config.h.in
@@ -383,6 +383,9 @@
 /* Enable Vulkan support */
 #undef SDL_VIDEO_VULKAN
 
+/* Enable Metal support */
+#undef SDL_VIDEO_METAL
+
 /* Enable system power support */
 #undef SDL_POWER_LINUX
 #undef SDL_POWER_WINDOWS
diff --git a/include/SDL_config_iphoneos.h b/include/SDL_config_iphoneos.h
index a3bf2e8..8137085 100644
--- a/include/SDL_config_iphoneos.h
+++ b/include/SDL_config_iphoneos.h
@@ -181,6 +181,10 @@
 #define SDL_VIDEO_VULKAN 1
 #endif
 
+#if SDL_PLATFORM_SUPPORTS_METAL
+#define SDL_VIDEO_METAL 1
+#endif
+
 /* Enable system power support */
 #define SDL_POWER_UIKIT 1
 
diff --git a/include/SDL_config_macosx.h b/include/SDL_config_macosx.h
index 16d0509..254c36d 100644
--- a/include/SDL_config_macosx.h
+++ b/include/SDL_config_macosx.h
@@ -193,9 +193,15 @@
 #define SDL_VIDEO_RENDER_OGL_ES2 1
 #endif
 
-#ifndef SDL_VIDEO_RENDER_METAL
 /* Metal only supported on 64-bit architectures with 10.11+ */
 #if TARGET_CPU_X86_64 && (MAC_OS_X_VERSION_MAX_ALLOWED >= 101100)
+#define SDL_PLATFORM_SUPPORTS_METAL    1
+#else
+#define SDL_PLATFORM_SUPPORTS_METAL    0
+#endif
+
+#ifndef SDL_VIDEO_RENDER_METAL
+#if SDL_PLATFORM_SUPPORTS_METAL
 #define SDL_VIDEO_RENDER_METAL    1
 #else
 #define SDL_VIDEO_RENDER_METAL    0
@@ -219,13 +225,22 @@
 #define SDL_VIDEO_OPENGL_GLX    1
 #endif
 
-/* Enable Vulkan support */
-/* Metal/Vulkan Portability only supported on 64-bit architectures with 10.11+ */
-#if TARGET_CPU_X86_64 && (MAC_OS_X_VERSION_MAX_ALLOWED >= 101100)
+/* Enable Vulkan and Metal support */
+#ifndef SDL_VIDEO_VULKAN
+#if SDL_PLATFORM_SUPPORTS_METAL
 #define SDL_VIDEO_VULKAN 1
 #else
 #define SDL_VIDEO_VULKAN 0
 #endif
+#endif
+
+#ifndef SDL_VIDEO_METAL
+#if SDL_PLATFORM_SUPPORTS_METAL
+#define SDL_VIDEO_METAL 1
+#else
+#define SDL_VIDEO_METAL 0
+#endif
+#endif
 
 /* Enable system power support */
 #define SDL_POWER_MACOSX 1
diff --git a/include/SDL_metal.h b/include/SDL_metal.h
new file mode 100644
index 0000000..0f1e0e9
--- /dev/null
+++ b/include/SDL_metal.h
@@ -0,0 +1,91 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ *  \file SDL_metal.h
+ *
+ *  Header file for functions to creating Metal layers and views on SDL windows.
+ */
+
+#ifndef SDL_metal_h_
+#define SDL_metal_h_
+
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  \brief A handle to a CAMetalLayer-backed NSView (macOS) or UIView (iOS/tvOS).
+ *
+ *  \note This can be cast directly to an NSView or UIView.
+ */
+typedef void *SDL_MetalView;
+
+/**
+ *  \name Metal support functions
+ */
+/* @{ */
+
+/**
+ *  \brief Create a CAMetalLayer-backed NSView/UIView and attach it to the
+ *        specified window.
+ *
+ *  On macOS, this does *not* associate a MTLDevice with the CAMetalLayer on its
+ *  own. It is up to user code to do that.
+ *
+ *  The returned handle can be casted directly to a NSView or UIView, and the
+ *  CAMetalLayer can be accessed from the view's 'layer' property.
+ *
+ *  \code
+ *  SDL_MetalView metalview = SDL_Metal_CreateView(window);
+ *  UIView *uiview = (__bridge UIView *)metalview;
+ *  CAMetalLayer *metallayer = (CAMetalLayer *)uiview.layer;
+ *  // [...]
+ *  SDL_Metal_DestroyView(metalview);
+ *  \endcode
+ *
+ *  \sa SDL_Metal_DestroyView
+ */
+extern DECLSPEC SDL_MetalView SDLCALL SDL_Metal_CreateView(SDL_Window * window);
+
+/**
+ *  \brief Destroy an existing SDL_MetalView object.
+ *
+ *  This should be called before SDL_DestroyWindow, if SDL_Metal_CreateView was
+ *  called after SDL_CreateWindow.
+ *
+ *  \sa SDL_Metal_CreateView
+ */
+extern DECLSPEC void SDLCALL SDL_Metal_DestroyView(SDL_MetalView view);
+
+/* @} *//* Metal support functions */
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_metal_h_ */
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index f8c5433..c769582 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -724,3 +724,5 @@
 #define SDL_RWwrite SDL_RWwrite_REAL
 #define SDL_RWclose SDL_RWclose_REAL
 #define SDL_LoadFile SDL_LoadFile_REAL
+#define SDL_Metal_CreateView SDL_Metal_CreateView_REAL
+#define SDL_Metal_DestroyView SDL_Metal_DestroyView_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index 5a22736..de5edba 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -780,3 +780,5 @@
 SDL_DYNAPI_PROC(size_t,SDL_RWwrite,(SDL_RWops *a, const void *b, size_t c, size_t d),(a,b,c,d),return)
 SDL_DYNAPI_PROC(int,SDL_RWclose,(SDL_RWops *a),(a),return)
 SDL_DYNAPI_PROC(void*,SDL_LoadFile,(const char *a, size_t *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_MetalView,SDL_Metal_CreateView,(SDL_Window *a),(a),return)
+SDL_DYNAPI_PROC(void,SDL_Metal_DestroyView,(SDL_MetalView a),(a),)
diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m
index 9233b8f..ee080f8 100644
--- a/src/render/metal/SDL_render_metal.m
+++ b/src/render/metal/SDL_render_metal.m
@@ -26,17 +26,17 @@
 #include "SDL_log.h"
 #include "SDL_assert.h"
 #include "SDL_syswm.h"
+#include "SDL_metal.h"
 #include "../SDL_sysrender.h"
 
-#ifdef __MACOSX__
-#include "../../video/cocoa/SDL_cocoametalview.h"
-#else
-#include "../../video/uikit/SDL_uikitmetalview.h"
-#endif
 #include <Availability.h>
 #import <Metal/Metal.h>
 #import <QuartzCore/CAMetalLayer.h>
 
+#ifdef __MACOSX__
+#import <AppKit/NSView.h>
+#endif
+
 /* Regenerate these with build-metal-shaders.sh */
 #ifdef __MACOSX__
 #include "SDL_shaders_metal_osx.h"
@@ -118,6 +118,7 @@
     @property (nonatomic, retain) id<MTLSamplerState> mtlsamplerlinear;
     @property (nonatomic, retain) id<MTLBuffer> mtlbufconstants;
     @property (nonatomic, retain) id<MTLBuffer> mtlbufquadindices;
+    @property (nonatomic, assign) SDL_MetalView mtlview;
     @property (nonatomic, retain) CAMetalLayer *mtllayer;
     @property (nonatomic, retain) MTLRenderPassDescriptor *mtlpassdesc;
     @property (nonatomic, assign) METAL_ShaderPipelines *activepipelines;
@@ -1475,6 +1476,8 @@
         }
 
         DestroyAllPipelines(data.allpipelines, data.pipelinescount);
+
+        SDL_Metal_DestroyView(data.mtlview);
     }
 
     SDL_free(renderer);
@@ -1501,6 +1504,8 @@
     SDL_Renderer *renderer = NULL;
     METAL_RenderData *data = NULL;
     id<MTLDevice> mtldevice = nil;
+    SDL_MetalView view = NULL;
+    CAMetalLayer *layer = nil;
     SDL_SysWMinfo syswm;
 
     SDL_VERSION(&syswm.version);
@@ -1527,26 +1532,36 @@
         return NULL;
     }
 
+    view = SDL_Metal_CreateView(window);
+
+    if (view == NULL) {
+        SDL_free(renderer);
+        return NULL;
+    }
+
     // !!! FIXME: error checking on all of this.
     data = [[METAL_RenderData alloc] init];
 
+    if (data == nil) {
+        SDL_Metal_DestroyView(view);
+        SDL_free(renderer);
+        return NULL;
+    }
+
     renderer->driverdata = (void*)CFBridgingRetain(data);
     renderer->window = window;
 
+    data.mtlview = view;
+
 #ifdef __MACOSX__
-    NSView *view = Cocoa_Mtl_AddMetalView(window);
-    CAMetalLayer *layer = (CAMetalLayer *)[view layer];
+    layer = (CAMetalLayer *)[(NSView *)view layer];
+#else
+    layer = (CAMetalLayer *)[(__bridge UIView *)view layer];
+#endif
 
     layer.device = mtldevice;
 
-    //layer.colorspace = nil;
-
-#else
-    UIView *view = UIKit_Mtl_AddMetalView(window);
-    CAMetalLayer *layer = (CAMetalLayer *)[view layer];
-#endif
-
-    // Necessary for RenderReadPixels.
+    /* Necessary for RenderReadPixels. */
     layer.framebufferOnly = NO;
 
     data.mtldevice = layer.device;
@@ -1763,7 +1778,6 @@
     [mtlsamplerlinear release];
     [mtlbufconstants release];
     [mtlbufquadindices release];
-    [view release];
     [data release];
     [mtldevice release];
 #endif
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index e88a8b6..ddaaf38 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -26,6 +26,7 @@
 #include "SDL_messagebox.h"
 #include "SDL_shape.h"
 #include "SDL_thread.h"
+#include "SDL_metal.h"
 
 #include "SDL_vulkan_internal.h"
 
@@ -276,6 +277,13 @@
 
     /* * * */
     /*
+     * Metal support
+     */
+    SDL_MetalView (*Metal_CreateView) (_THIS, SDL_Window * window);
+    void (*Metal_DestroyView) (_THIS, SDL_MetalView view);
+
+    /* * * */
+    /*
      * Event manager functions
      */
     void (*PumpEvents) (_THIS);
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index c63f746..35599f4 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -4183,4 +4183,25 @@
     }
 }
 
+SDL_MetalView
+SDL_Metal_CreateView(SDL_Window * window)
+{
+    CHECK_WINDOW_MAGIC(window, NULL);
+
+    if (_this->Metal_CreateView) {
+        return _this->Metal_CreateView(_this, window);
+    } else {
+        SDL_SetError("Metal is not supported.");
+        return NULL;
+    }
+}
+
+void
+SDL_Metal_DestroyView(SDL_MetalView view)
+{
+    if (_this && view && _this->Metal_DestroyView) {
+        _this->Metal_DestroyView(_this, view);
+    }
+}
+
 /* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/cocoa/SDL_cocoametalview.h b/src/video/cocoa/SDL_cocoametalview.h
index 6dafef3..77e7256 100644
--- a/src/video/cocoa/SDL_cocoametalview.h
+++ b/src/video/cocoa/SDL_cocoametalview.h
@@ -31,7 +31,7 @@
 #import "../SDL_sysvideo.h"
 #import "SDL_cocoawindow.h"
 
-#if SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_RENDER_METAL)
+#if SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL)
 
 #import <Cocoa/Cocoa.h>
 #import <Metal/Metal.h>
@@ -51,11 +51,12 @@
 
 @end
 
-SDL_cocoametalview* Cocoa_Mtl_AddMetalView(SDL_Window* window);
+SDL_MetalView Cocoa_Metal_CreateView(_THIS, SDL_Window * window);
+void Cocoa_Metal_DestroyView(_THIS, SDL_MetalView view);
 
-void Cocoa_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h);
+void Cocoa_Metal_GetDrawableSize(SDL_Window * window, int * w, int * h);
 
-#endif /* SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_RENDER_METAL) */
+#endif /* SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL) */
 
 #endif /* SDL_cocoametalview_h_ */
 
diff --git a/src/video/cocoa/SDL_cocoametalview.m b/src/video/cocoa/SDL_cocoametalview.m
index 3d7e147..b3b8b84 100644
--- a/src/video/cocoa/SDL_cocoametalview.m
+++ b/src/video/cocoa/SDL_cocoametalview.m
@@ -27,7 +27,7 @@
 
 #import "SDL_cocoametalview.h"
 
-#if SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_RENDER_METAL)
+#if SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL)
 
 #include "SDL_assert.h"
 
@@ -100,22 +100,38 @@
 
 @end
 
-SDL_cocoametalview*
-Cocoa_Mtl_AddMetalView(SDL_Window* window)
-{
+SDL_MetalView
+Cocoa_Metal_CreateView(_THIS, SDL_Window * window)
+{ @autoreleasepool {
     SDL_WindowData* data = (__bridge SDL_WindowData *)window->driverdata;
     NSView *view = data->nswindow.contentView;
     BOOL highDPI = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
-    SDL_cocoametalview *metalview;
+    SDL_cocoametalview *newview;
+    SDL_MetalView metalview;
 
-    metalview = [[SDL_cocoametalview alloc] initWithFrame:view.frame highDPI:highDPI];
-    [view addSubview:metalview];
+    newview = [[SDL_cocoametalview alloc] initWithFrame:view.frame highDPI:highDPI];
+    if (newview == nil) {
+        return NULL;
+    }
+
+    [view addSubview:newview];
+
+    metalview = (SDL_MetalView)CFBridgingRetain(newview);
+    [newview release];
+
     return metalview;
-}
+}}
 
 void
-Cocoa_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h)
-{
+Cocoa_Metal_DestroyView(_THIS, SDL_MetalView view)
+{ @autoreleasepool {
+    SDL_cocoametalview *metalview = CFBridgingRelease(view);
+    [metalview removeFromSuperview];
+}}
+
+void
+Cocoa_Metal_GetDrawableSize(SDL_Window * window, int * w, int * h)
+{ @autoreleasepool {
     SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
     NSView *view = data->nswindow.contentView;
     SDL_cocoametalview* metalview = [view viewWithTag:METALVIEW_TAG];
@@ -131,8 +147,8 @@
     } else {
         SDL_GetWindowSize(window, w, h);
     }
-}
+}}
 
-#endif /* SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_RENDER_METAL) */
+#endif /* SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL) */
 
 /* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m
index feb8e08..7384d6c 100644
--- a/src/video/cocoa/SDL_cocoavideo.m
+++ b/src/video/cocoa/SDL_cocoavideo.m
@@ -27,6 +27,7 @@
 #include "SDL_cocoavideo.h"
 #include "SDL_cocoashape.h"
 #include "SDL_cocoavulkan.h"
+#include "SDL_cocoametalview.h"
 #include "SDL_assert.h"
 
 /* Initialization/Query functions */
@@ -142,6 +143,11 @@
     device->Vulkan_GetDrawableSize = Cocoa_Vulkan_GetDrawableSize;
 #endif
 
+#if SDL_VIDEO_METAL
+    device->Metal_CreateView = Cocoa_Metal_CreateView;
+    device->Metal_DestroyView = Cocoa_Metal_DestroyView;
+#endif
+
     device->StartTextInput = Cocoa_StartTextInput;
     device->StopTextInput = Cocoa_StopTextInput;
     device->SetTextInputRect = Cocoa_SetTextInputRect;
diff --git a/src/video/cocoa/SDL_cocoavulkan.m b/src/video/cocoa/SDL_cocoavulkan.m
index 4801d76..fe2738c 100644
--- a/src/video/cocoa/SDL_cocoavulkan.m
+++ b/src/video/cocoa/SDL_cocoavulkan.m
@@ -194,6 +194,7 @@
                                             "vkCreateMacOSSurfaceMVK");
     VkMacOSSurfaceCreateInfoMVK createInfo = {};
     VkResult result;
+    SDL_MetalView metalview;
 
     if (!_this->vulkan_config.loader_handle) {
         SDL_SetError("Vulkan is not loaded");
@@ -205,23 +206,38 @@
                      " extension is not enabled in the Vulkan instance.");
         return SDL_FALSE;
     }
+
+    metalview = Cocoa_Metal_CreateView(_this, window);
+    if (metalview == NULL) {
+        return SDL_FALSE;
+    }
+
     createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
     createInfo.pNext = NULL;
     createInfo.flags = 0;
-    createInfo.pView = Cocoa_Mtl_AddMetalView(window);
+    createInfo.pView = (const void *)metalview;
     result = vkCreateMacOSSurfaceMVK(instance, &createInfo,
                                        NULL, surface);
     if (result != VK_SUCCESS) {
+        Cocoa_Metal_DestroyView(_this, metalview);
         SDL_SetError("vkCreateMacOSSurfaceMVK failed: %s",
                      SDL_Vulkan_GetResultString(result));
         return SDL_FALSE;
     }
+
+    /* Unfortunately there's no SDL_Vulkan_DestroySurface function we can call
+     * Metal_DestroyView from. Right now the metal view's ref count is +2 (one
+     * from returning a new view object in CreateView, and one because it's
+     * a subview of the window.) If we release the view here to make it +1, it
+     * will be destroyed when the window is destroyed. */
+    CFBridgingRelease(metalview);
+
     return SDL_TRUE;
 }
 
 void Cocoa_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
 {
-    Cocoa_Mtl_GetDrawableSize(window, w, h);
+    Cocoa_Metal_GetDrawableSize(window, w, h);
 }
 
 #endif
diff --git a/src/video/uikit/SDL_uikitmetalview.h b/src/video/uikit/SDL_uikitmetalview.h
index 02d5671..ccafdcb 100644
--- a/src/video/uikit/SDL_uikitmetalview.h
+++ b/src/video/uikit/SDL_uikitmetalview.h
@@ -29,10 +29,10 @@
 #ifndef SDL_uikitmetalview_h_
 #define SDL_uikitmetalview_h_
 
-#import "../SDL_sysvideo.h"
-#import "SDL_uikitwindow.h"
+#include "../SDL_sysvideo.h"
+#include "SDL_uikitwindow.h"
 
-#if SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_RENDER_METAL || SDL_VIDEO_VULKAN)
+#if SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL)
 
 #import <UIKit/UIKit.h>
 #import <Metal/Metal.h>
@@ -47,11 +47,12 @@
 
 @end
 
-SDL_uikitmetalview* UIKit_Mtl_AddMetalView(SDL_Window* window);
+SDL_MetalView UIKit_Metal_CreateView(_THIS, SDL_Window * window);
+void UIKit_Metal_DestroyView(_THIS, SDL_MetalView view);
 
-void UIKit_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h);
+void UIKit_Metal_GetDrawableSize(SDL_Window * window, int * w, int * h);
 
-#endif /* SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_RENDER_METAL || SDL_VIDEO_VULKAN) */
+#endif /* SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL) */
 
 #endif /* SDL_uikitmetalview_h_ */
 
diff --git a/src/video/uikit/SDL_uikitmetalview.m b/src/video/uikit/SDL_uikitmetalview.m
index c9c93c0..548ed0d 100644
--- a/src/video/uikit/SDL_uikitmetalview.m
+++ b/src/video/uikit/SDL_uikitmetalview.m
@@ -28,7 +28,7 @@
 
 #include "../../SDL_internal.h"
 
-#if SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_RENDER_METAL || SDL_VIDEO_VULKAN)
+#if SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL)
 
 #import "../SDL_sysvideo.h"
 #import "SDL_uikitwindow.h"
@@ -73,16 +73,12 @@
 
 @end
 
-SDL_uikitmetalview*
-UIKit_Mtl_AddMetalView(SDL_Window* window)
-{
+SDL_MetalView
+UIKit_Metal_CreateView(_THIS, SDL_Window * window)
+{ @autoreleasepool {
     SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
-    SDL_uikitview *view = (SDL_uikitview*)data.uiwindow.rootViewController.view;
     CGFloat scale = 1.0;
-
-    if ([view isKindOfClass:[SDL_uikitmetalview class]]) {
-        return (SDL_uikitmetalview *)view;
-    }
+    SDL_uikitmetalview *metalview;
 
     if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
         /* Set the scale to the natural scale factor of the screen - then
@@ -96,16 +92,26 @@
             scale = data.uiwindow.screen.scale;
         }
     }
-    SDL_uikitmetalview *metalview
-         = [[SDL_uikitmetalview alloc] initWithFrame:view.frame
-                                               scale:scale];
+
+    metalview = [[SDL_uikitmetalview alloc] initWithFrame:data.uiwindow.bounds
+                                                    scale:scale];
     [metalview setSDLWindow:window];
 
-    return metalview;
-}
+    return (void*)CFBridgingRetain(metalview);
+}}
 
 void
-UIKit_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h)
+UIKit_Metal_DestroyView(_THIS, SDL_MetalView view)
+{ @autoreleasepool {
+    SDL_uikitmetalview *metalview = CFBridgingRelease(view);
+
+    if ([metalview isKindOfClass:[SDL_uikitmetalview class]]) {
+        [metalview setSDLWindow:NULL];
+    }
+}}
+
+void
+UIKit_Metal_GetDrawableSize(SDL_Window * window, int * w, int * h)
 {
     @autoreleasepool {
         SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
@@ -126,4 +132,4 @@
     }
 }
 
-#endif /* SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_RENDER_METAL || SDL_VIDEO_VULKAN) */
+#endif /* SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL) */
diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m
index cea40b2..26ff02a 100644
--- a/src/video/uikit/SDL_uikitvideo.m
+++ b/src/video/uikit/SDL_uikitvideo.m
@@ -38,6 +38,7 @@
 #include "SDL_uikitopengles.h"
 #include "SDL_uikitclipboard.h"
 #include "SDL_uikitvulkan.h"
+#include "SDL_uikitmetalview.h"
 
 #define UIKITVID_DRIVER_NAME "uikit"
 
@@ -133,6 +134,11 @@
         device->Vulkan_GetDrawableSize = UIKit_Vulkan_GetDrawableSize;
 #endif
 
+#if SDL_VIDEO_METAL
+        device->Metal_CreateView = UIKit_Metal_CreateView;
+        device->Metal_DestroyView = UIKit_Metal_DestroyView;
+#endif
+
         device->gl_config.accelerated = 1;
 
         return device;
diff --git a/src/video/uikit/SDL_uikitvulkan.m b/src/video/uikit/SDL_uikitvulkan.m
index c4b779d..c95f6fe 100644
--- a/src/video/uikit/SDL_uikitvulkan.m
+++ b/src/video/uikit/SDL_uikitvulkan.m
@@ -200,6 +200,7 @@
                                             "vkCreateIOSSurfaceMVK");
     VkIOSSurfaceCreateInfoMVK createInfo = {};
     VkResult result;
+    SDL_MetalView metalview;
 
     if (!_this->vulkan_config.loader_handle) {
         SDL_SetError("Vulkan is not loaded");
@@ -212,24 +213,37 @@
         return SDL_FALSE;
     }
 
+    metalview = UIKit_Metal_CreateView(_this, window);
+    if (metalview == NULL) {
+        return SDL_FALSE;
+    }
+
     createInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK;
     createInfo.pNext = NULL;
     createInfo.flags = 0;
-    createInfo.pView = (__bridge void *)UIKit_Mtl_AddMetalView(window);
+    createInfo.pView = (const void *)metalview;
     result = vkCreateIOSSurfaceMVK(instance, &createInfo,
                                        NULL, surface);
     if (result != VK_SUCCESS) {
+        UIKit_Metal_DestroyView(_this, metalview);
         SDL_SetError("vkCreateIOSSurfaceMVK failed: %s",
                      SDL_Vulkan_GetResultString(result));
         return SDL_FALSE;
     }
 
+    /* Unfortunately there's no SDL_Vulkan_DestroySurface function we can call
+     * Metal_DestroyView from. Right now the metal view's ref count is +2 (one
+     * from returning a new view object in CreateView, and one because it's
+     * a subview of the window.) If we release the view here to make it +1, it
+     * will be destroyed when the window is destroyed. */
+    CFBridgingRelease(metalview);
+
     return SDL_TRUE;
 }
 
 void UIKit_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
 {
-    UIKit_Mtl_GetDrawableSize(window, w, h);
+    UIKit_Metal_GetDrawableSize(window, w, h);
 }
 
 #endif