mirror of
https://github.com/encounter/SDL.git
synced 2025-12-16 08:27:05 +00:00
metal: Added some support interfaces to Apple's Metal API (thanks, Caleb!).
Caleb Cornett's comments: "A few weeks ago, Alex added a partial Metal API to SDL2: https://hg.libsdl.org/SDL/rev/22c8e7cd8d38 I noticed it was missing a few features that would help Metal become a first-class citizen in SDL, so I went ahead and wrote them! Here are the new APIs: 1. SDL_WINDOW_METAL flag for SDL_CreateWindow(). This allows the programmer to specify that they intend to create a window for use with SDL_MetalView. The flag is used to ensure correct usage of the API and to prevent accidentally defaulting to OpenGL on iOS. 2. SDL_Metal_GetLayer(). This function takes a SDL_MetalView and returns a pointer to the view's backing CAMetalLayer. This simplifies things considerably, since in the current version of the SDL_Metal API the programmer is required to bridge-cast a SDL_MetalView handle to an NSView or UIView (depending on the platform) and then extract the layer from there. SDL_Metal_GetLayer automatically handles all of that, making the operation simple and cross-platform. 3. SDL_Metal_GetDrawableSize(). This function already exists in the current SDL_Metal API (and is used behind-the-scenes for SDL_Vulkan_GetDrawableSize on Apple platforms) but was not publicly exposed. My patch exposes this function for public use. It works just like you'd expect. Tested on macOS 10.14 and iOS 12.4." Fixes Bugzilla #4796.
This commit is contained in:
@@ -281,6 +281,8 @@ struct SDL_VideoDevice
|
||||
*/
|
||||
SDL_MetalView (*Metal_CreateView) (_THIS, SDL_Window * window);
|
||||
void (*Metal_DestroyView) (_THIS, SDL_MetalView view);
|
||||
void *(*Metal_GetLayer) (_THIS, SDL_MetalView view);
|
||||
void (*Metal_GetDrawableSize) (_THIS, SDL_Window * window, int *w, int *h);
|
||||
|
||||
/* * * */
|
||||
/*
|
||||
|
||||
@@ -1366,7 +1366,7 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
|
||||
}
|
||||
|
||||
#define CREATE_FLAGS \
|
||||
(SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN | SDL_WINDOW_MINIMIZED)
|
||||
(SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN | SDL_WINDOW_MINIMIZED | SDL_WINDOW_METAL)
|
||||
|
||||
static SDL_INLINE SDL_bool
|
||||
IsAcceptingDragAndDrop(void)
|
||||
@@ -1455,7 +1455,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
|
||||
|
||||
/* Some platforms have OpenGL enabled by default */
|
||||
#if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__ || __NACL__
|
||||
if (!_this->is_dummy && !(flags & SDL_WINDOW_VULKAN) && !SDL_IsVideoContextExternal()) {
|
||||
if (!_this->is_dummy && !(flags & SDL_WINDOW_VULKAN) && !(flags & SDL_WINDOW_METAL) && !SDL_IsVideoContextExternal()) {
|
||||
flags |= SDL_WINDOW_OPENGL;
|
||||
}
|
||||
#endif
|
||||
@@ -1487,6 +1487,24 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & SDL_WINDOW_METAL) {
|
||||
if (!_this->Metal_CreateView) {
|
||||
SDL_SetError("Metal support is either not configured in SDL "
|
||||
"or not available in current SDL video driver "
|
||||
"(%s) or platform", _this->name);
|
||||
return NULL;
|
||||
}
|
||||
if (flags & SDL_WINDOW_OPENGL) {
|
||||
SDL_SetError("Metal and OpenGL not supported on same window");
|
||||
return NULL;
|
||||
}
|
||||
if (flags & SDL_WINDOW_VULKAN) {
|
||||
SDL_SetError("Metal and Vulkan not supported on same window. "
|
||||
"To use MoltenVK, set SDL_WINDOW_VULKAN only.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unless the user has specified the high-DPI disabling hint, respect the
|
||||
* SDL_WINDOW_ALLOW_HIGHDPI flag.
|
||||
*/
|
||||
@@ -1688,11 +1706,26 @@ SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((window->flags & SDL_WINDOW_METAL) != (flags & SDL_WINDOW_METAL)) {
|
||||
SDL_SetError("Can't change SDL_WINDOW_METAL window flag");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((window->flags & SDL_WINDOW_VULKAN) && (flags & SDL_WINDOW_OPENGL)) {
|
||||
SDL_SetError("Vulkan and OpenGL not supported on same window");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((window->flags & SDL_WINDOW_METAL) && (flags & SDL_WINDOW_OPENGL)) {
|
||||
SDL_SetError("Metal and OpenGL not supported on same window");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((window->flags & SDL_WINDOW_METAL) && (flags & SDL_WINDOW_VULKAN)) {
|
||||
SDL_SetError("Metal and Vulkan not supported on same window");
|
||||
return -1;
|
||||
}
|
||||
|
||||
window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
|
||||
window->last_fullscreen_flags = window->flags;
|
||||
window->is_destroying = SDL_FALSE;
|
||||
@@ -4223,6 +4256,11 @@ 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;
|
||||
}
|
||||
|
||||
if (_this->Metal_CreateView) {
|
||||
return _this->Metal_CreateView(_this, window);
|
||||
} else {
|
||||
@@ -4239,4 +4277,31 @@ SDL_Metal_DestroyView(SDL_MetalView view)
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
SDL_Metal_GetLayer(SDL_MetalView view)
|
||||
{
|
||||
if (_this && _this->Metal_GetLayer) {
|
||||
if (view) {
|
||||
return _this->Metal_GetLayer(_this, view);
|
||||
} else {
|
||||
SDL_InvalidParamError("view");
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_SetError("Metal is not supported.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_Metal_GetDrawableSize(SDL_Window * window, int *w, int *h)
|
||||
{
|
||||
CHECK_WINDOW_MAGIC(window,);
|
||||
|
||||
if (_this->Metal_GetDrawableSize) {
|
||||
_this->Metal_GetDrawableSize(_this, window, w, h);
|
||||
} else {
|
||||
SDL_GetWindowSize(window, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -59,8 +59,8 @@
|
||||
|
||||
SDL_MetalView Cocoa_Metal_CreateView(_THIS, SDL_Window * window);
|
||||
void Cocoa_Metal_DestroyView(_THIS, SDL_MetalView view);
|
||||
|
||||
void Cocoa_Metal_GetDrawableSize(SDL_Window * window, int * w, int * h);
|
||||
void *Cocoa_Metal_GetLayer(_THIS, SDL_MetalView view);
|
||||
void Cocoa_Metal_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h);
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL) */
|
||||
|
||||
|
||||
@@ -157,8 +157,15 @@ Cocoa_Metal_DestroyView(_THIS, SDL_MetalView view)
|
||||
[metalview removeFromSuperview];
|
||||
}}
|
||||
|
||||
void *
|
||||
Cocoa_Metal_GetLayer(_THIS, SDL_MetalView view)
|
||||
{ @autoreleasepool {
|
||||
SDL_cocoametalview *cocoaview = (__bridge SDL_cocoametalview *)view;
|
||||
return (__bridge void *)cocoaview.layer;
|
||||
}}
|
||||
|
||||
void
|
||||
Cocoa_Metal_GetDrawableSize(SDL_Window * window, int * w, int * h)
|
||||
Cocoa_Metal_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
|
||||
{ @autoreleasepool {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
|
||||
NSView *view = data->nswindow.contentView;
|
||||
|
||||
@@ -146,6 +146,8 @@ Cocoa_CreateDevice(int devindex)
|
||||
#if SDL_VIDEO_METAL
|
||||
device->Metal_CreateView = Cocoa_Metal_CreateView;
|
||||
device->Metal_DestroyView = Cocoa_Metal_DestroyView;
|
||||
device->Metal_GetLayer = Cocoa_Metal_GetLayer;
|
||||
device->Metal_GetDrawableSize = Cocoa_Metal_GetDrawableSize;
|
||||
#endif
|
||||
|
||||
device->StartTextInput = Cocoa_StartTextInput;
|
||||
|
||||
@@ -236,7 +236,7 @@ SDL_bool Cocoa_Vulkan_CreateSurface(_THIS,
|
||||
|
||||
void Cocoa_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
|
||||
{
|
||||
Cocoa_Metal_GetDrawableSize(window, w, h);
|
||||
Cocoa_Metal_GetDrawableSize(_this, window, w, h);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
|
||||
SDL_MetalView UIKit_Metal_CreateView(_THIS, SDL_Window * window);
|
||||
void UIKit_Metal_DestroyView(_THIS, SDL_MetalView view);
|
||||
|
||||
void UIKit_Metal_GetDrawableSize(SDL_Window * window, int * w, int * h);
|
||||
void *UIKit_Metal_GetLayer(_THIS, SDL_MetalView view);
|
||||
void UIKit_Metal_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h);
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL) */
|
||||
|
||||
|
||||
@@ -110,8 +110,15 @@ UIKit_Metal_DestroyView(_THIS, SDL_MetalView view)
|
||||
}
|
||||
}}
|
||||
|
||||
void *
|
||||
UIKit_Metal_GetLayer(_THIS, SDL_MetalView view)
|
||||
{ @autoreleasepool {
|
||||
SDL_uikitview *uiview = (__bridge SDL_uikitview *)view;
|
||||
return (__bridge void *)uiview.layer;
|
||||
}}
|
||||
|
||||
void
|
||||
UIKit_Metal_GetDrawableSize(SDL_Window * window, int * w, int * h)
|
||||
UIKit_Metal_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
|
||||
|
||||
@@ -140,6 +140,8 @@ UIKit_CreateDevice(int devindex)
|
||||
#if SDL_VIDEO_METAL
|
||||
device->Metal_CreateView = UIKit_Metal_CreateView;
|
||||
device->Metal_DestroyView = UIKit_Metal_DestroyView;
|
||||
device->Metal_GetLayer = UIKit_Metal_GetLayer;
|
||||
device->Metal_GetDrawableSize = UIKit_Metal_GetDrawableSize;
|
||||
#endif
|
||||
|
||||
device->gl_config.accelerated = 1;
|
||||
|
||||
@@ -243,7 +243,7 @@ SDL_bool UIKit_Vulkan_CreateSurface(_THIS,
|
||||
|
||||
void UIKit_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
|
||||
{
|
||||
UIKit_Metal_GetDrawableSize(window, w, h);
|
||||
UIKit_Metal_GetDrawableSize(_this, window, w, h);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user