mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-16 14:56:00 +00:00
vulkan: Initial Vulkan support!
This work was done by Jacob Lifshay and Mark Callow; I'm just merging it into revision control.
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#include "SDL_messagebox.h"
|
||||
#include "SDL_shape.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_vulkan.h"
|
||||
|
||||
/* The SDL video driver */
|
||||
|
||||
@@ -260,6 +261,16 @@ struct SDL_VideoDevice
|
||||
int (*GL_SwapWindow) (_THIS, SDL_Window * window);
|
||||
void (*GL_DeleteContext) (_THIS, SDL_GLContext context);
|
||||
|
||||
/* * * */
|
||||
/*
|
||||
* Vulkan support
|
||||
*/
|
||||
int (*Vulkan_LoadLibrary) (_THIS, const char *path);
|
||||
void (*Vulkan_UnloadLibrary) (_THIS);
|
||||
SDL_bool (*Vulkan_GetInstanceExtensions) (_THIS, SDL_Window *window, unsigned *count, const char **names);
|
||||
SDL_bool (*Vulkan_CreateSurface) (_THIS, SDL_Window *window, VkInstance instance, VkSurfaceKHR *surface);
|
||||
void (*Vulkan_GetDrawableSize) (_THIS, SDL_Window * window, int *w, int *h);
|
||||
|
||||
/* * * */
|
||||
/*
|
||||
* Event manager functions
|
||||
@@ -348,6 +359,17 @@ struct SDL_VideoDevice
|
||||
SDL_TLSID current_glwin_tls;
|
||||
SDL_TLSID current_glctx_tls;
|
||||
|
||||
/* * * */
|
||||
/* Data used by the Vulkan drivers */
|
||||
struct
|
||||
{
|
||||
void *vkGetInstanceProcAddr;
|
||||
void *vkEnumerateInstanceExtensionProperties;
|
||||
int loader_loaded;
|
||||
char loader_path[256];
|
||||
void *loader_handle;
|
||||
} vulkan_config;
|
||||
|
||||
/* * * */
|
||||
/* Data private to this driver */
|
||||
void *driverdata;
|
||||
|
@@ -1329,7 +1329,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_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)
|
||||
|
||||
static void
|
||||
SDL_FinishWindowCreation(SDL_Window *window, Uint32 flags)
|
||||
@@ -1384,7 +1384,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) {
|
||||
if (!_this->is_dummy && !(flags & SDL_WINDOW_VULKAN)) {
|
||||
flags |= SDL_WINDOW_OPENGL;
|
||||
}
|
||||
#endif
|
||||
@@ -1398,6 +1398,25 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
|
||||
}
|
||||
}
|
||||
|
||||
if(flags & SDL_WINDOW_VULKAN)
|
||||
{
|
||||
if(!_this->Vulkan_CreateSurface)
|
||||
{
|
||||
SDL_SetError("Vulkan support is either not configured in SDL "
|
||||
"or not available in video driver");
|
||||
return NULL;
|
||||
}
|
||||
if(flags & SDL_WINDOW_OPENGL)
|
||||
{
|
||||
SDL_SetError("Vulkan and OpenGL not supported on same window");
|
||||
return NULL;
|
||||
}
|
||||
if(SDL_Vulkan_LoadLibrary(NULL) < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unless the user has specified the high-DPI disabling hint, respect the
|
||||
* SDL_WINDOW_ALLOW_HIGHDPI flag.
|
||||
*/
|
||||
@@ -1573,6 +1592,16 @@ SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
|
||||
}
|
||||
}
|
||||
|
||||
if ((window->flags & SDL_WINDOW_VULKAN) != (flags & SDL_WINDOW_VULKAN)) {
|
||||
SDL_SetError("Can't change SDL_WINDOW_VULKAN 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;
|
||||
}
|
||||
|
||||
window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
|
||||
window->last_fullscreen_flags = window->flags;
|
||||
window->is_destroying = SDL_FALSE;
|
||||
@@ -2632,6 +2661,9 @@ SDL_DestroyWindow(SDL_Window * window)
|
||||
if (window->flags & SDL_WINDOW_OPENGL) {
|
||||
SDL_GL_UnloadLibrary();
|
||||
}
|
||||
if (window->flags & SDL_WINDOW_VULKAN) {
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
}
|
||||
|
||||
display = SDL_GetDisplayForWindow(window);
|
||||
if (display->fullscreen_window == window) {
|
||||
@@ -3946,4 +3978,128 @@ void SDL_OnApplicationDidBecomeActive(void)
|
||||
}
|
||||
}
|
||||
|
||||
#define NOT_A_VULKAN_WINDOW "The specified window isn't a Vulkan window."
|
||||
|
||||
int SDL_Vulkan_LoadLibrary(const char *path)
|
||||
{
|
||||
int retval;
|
||||
if(!_this)
|
||||
{
|
||||
SDL_UninitializedVideo();
|
||||
return -1;
|
||||
}
|
||||
if(_this->vulkan_config.loader_loaded)
|
||||
{
|
||||
if(path && SDL_strcmp(path, _this->vulkan_config.loader_path) != 0)
|
||||
{
|
||||
return SDL_SetError("Vulkan loader library already loaded");
|
||||
}
|
||||
retval = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!_this->Vulkan_LoadLibrary)
|
||||
{
|
||||
return SDL_SetError("No Vulkan support in video driver");
|
||||
}
|
||||
retval = _this->Vulkan_LoadLibrary(_this, path);
|
||||
}
|
||||
if(retval == 0)
|
||||
{
|
||||
_this->vulkan_config.loader_loaded++;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void *SDL_Vulkan_GetVkGetInstanceProcAddr(void)
|
||||
{
|
||||
if(!_this)
|
||||
{
|
||||
SDL_UninitializedVideo();
|
||||
return NULL;
|
||||
}
|
||||
if(!_this->vulkan_config.loader_loaded)
|
||||
{
|
||||
SDL_SetError("No Vulkan loader has been loaded");
|
||||
}
|
||||
return _this->vulkan_config.vkGetInstanceProcAddr;
|
||||
}
|
||||
|
||||
void SDL_Vulkan_UnloadLibrary(void)
|
||||
{
|
||||
if(!_this)
|
||||
{
|
||||
SDL_UninitializedVideo();
|
||||
return;
|
||||
}
|
||||
if(_this->vulkan_config.loader_loaded > 0)
|
||||
{
|
||||
if(--_this->vulkan_config.loader_loaded > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(_this->Vulkan_UnloadLibrary)
|
||||
{
|
||||
_this->Vulkan_UnloadLibrary(_this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool SDL_Vulkan_GetInstanceExtensions(SDL_Window *window, unsigned *count, const char **names)
|
||||
{
|
||||
CHECK_WINDOW_MAGIC(window, SDL_FALSE);
|
||||
|
||||
if(!(window->flags & SDL_WINDOW_VULKAN))
|
||||
{
|
||||
SDL_SetError(NOT_A_VULKAN_WINDOW);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if(!count)
|
||||
{
|
||||
SDL_SetError("invalid count");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
return _this->Vulkan_GetInstanceExtensions(_this, window, count, names);
|
||||
}
|
||||
|
||||
SDL_bool SDL_Vulkan_CreateSurface(SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface)
|
||||
{
|
||||
CHECK_WINDOW_MAGIC(window, SDL_FALSE);
|
||||
|
||||
if(!(window->flags & SDL_WINDOW_VULKAN))
|
||||
{
|
||||
SDL_SetError(NOT_A_VULKAN_WINDOW);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if(!instance)
|
||||
{
|
||||
SDL_SetError("invalid instance");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if(!surface)
|
||||
{
|
||||
SDL_SetError("invalid surface");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
return _this->Vulkan_CreateSurface(_this, window, instance, surface);
|
||||
}
|
||||
|
||||
void SDL_Vulkan_GetDrawableSize(SDL_Window * window, int *w, int *h)
|
||||
{
|
||||
CHECK_WINDOW_MAGIC(window,);
|
||||
|
||||
if (_this->Vulkan_GetDrawableSize) {
|
||||
_this->Vulkan_GetDrawableSize(_this, window, w, h);
|
||||
} else {
|
||||
SDL_GetWindowSize(window, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
80
src/video/SDL_vulkan_internal.h
Normal file
80
src/video/SDL_vulkan_internal.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 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.
|
||||
*/
|
||||
#ifndef _SDL_vulkan_internal_h
|
||||
#define _SDL_vulkan_internal_h
|
||||
|
||||
#include "../SDL_internal.h"
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
|
||||
#if defined(SDL_LOADSO_DISABLED)
|
||||
#undef SDL_VIDEO_VULKAN_SURFACE
|
||||
#define SDL_VIDEO_VULKAN_SURFACE 0
|
||||
#endif
|
||||
|
||||
#if SDL_VIDEO_DRIVER_ANDROID
|
||||
#define VK_USE_PLATFORM_ANDROID_KHR
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_COCOA
|
||||
#define VK_USE_PLATFORM_MACOS_MVK
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_MIR
|
||||
#define VK_USE_PLATFORM_MIR_KHR
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_UIKIT
|
||||
#define VK_USE_PLATFORM_IOS_MVK
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_WAYLAND
|
||||
#define VK_USE_PLATFORM_WAYLAND_KHR
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_WINDOWS
|
||||
#define VK_USE_PLATFORM_WIN32_KHR
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_X11
|
||||
#define VK_USE_PLATFORM_XLIB_KHR
|
||||
#define VK_USE_PLATFORM_XCB_KHR
|
||||
#endif
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE
|
||||
|
||||
/* Need vulkan.h for the following declarations. Must ensure the first
|
||||
* inclusion of vulkan has the appropriate USE_PLATFORM defined, hence
|
||||
* the above. */
|
||||
#define VK_NO_PROTOTYPES
|
||||
#include "vulkan/vulkan.h"
|
||||
|
||||
extern const char *SDL_Vulkan_GetResultString(VkResult result);
|
||||
|
||||
extern VkExtensionProperties *SDL_Vulkan_CreateInstanceExtensionsList(
|
||||
PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties,
|
||||
Uint32 *extensionCount); /* free returned list with SDL_free */
|
||||
|
||||
/* Implements functionality of SDL_Vulkan_GetInstanceExtensions for a list of
|
||||
* names passed in nameCount and names. */
|
||||
extern SDL_bool SDL_Vulkan_GetInstanceExtensions_Helper(unsigned *userCount,
|
||||
const char **userNames,
|
||||
unsigned nameCount,
|
||||
const char *const *names);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
191
src/video/SDL_vulkan_utils.c
Normal file
191
src/video/SDL_vulkan_utils.c
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 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.
|
||||
*/
|
||||
#include "../SDL_internal.h"
|
||||
|
||||
#include "SDL_vulkan_internal.h"
|
||||
#include "SDL_error.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE
|
||||
|
||||
/* Based on the headers found in
|
||||
* https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers
|
||||
*/
|
||||
#if VK_HEADER_VERSION < 22
|
||||
enum
|
||||
{
|
||||
VK_ERROR_FRAGMENTED_POOL = -12,
|
||||
};
|
||||
#endif
|
||||
#if VK_HEADER_VERSION < 38
|
||||
enum {
|
||||
VK_ERROR_OUT_OF_POOL_MEMORY_KHR = -1000069000
|
||||
};
|
||||
#endif
|
||||
|
||||
const char *SDL_Vulkan_GetResultString(VkResult result)
|
||||
{
|
||||
switch((int)result)
|
||||
{
|
||||
case VK_SUCCESS:
|
||||
return "VK_SUCCESS";
|
||||
case VK_NOT_READY:
|
||||
return "VK_NOT_READY";
|
||||
case VK_TIMEOUT:
|
||||
return "VK_TIMEOUT";
|
||||
case VK_EVENT_SET:
|
||||
return "VK_EVENT_SET";
|
||||
case VK_EVENT_RESET:
|
||||
return "VK_EVENT_RESET";
|
||||
case VK_INCOMPLETE:
|
||||
return "VK_INCOMPLETE";
|
||||
case VK_ERROR_OUT_OF_HOST_MEMORY:
|
||||
return "VK_ERROR_OUT_OF_HOST_MEMORY";
|
||||
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
|
||||
return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
|
||||
case VK_ERROR_INITIALIZATION_FAILED:
|
||||
return "VK_ERROR_INITIALIZATION_FAILED";
|
||||
case VK_ERROR_DEVICE_LOST:
|
||||
return "VK_ERROR_DEVICE_LOST";
|
||||
case VK_ERROR_MEMORY_MAP_FAILED:
|
||||
return "VK_ERROR_MEMORY_MAP_FAILED";
|
||||
case VK_ERROR_LAYER_NOT_PRESENT:
|
||||
return "VK_ERROR_LAYER_NOT_PRESENT";
|
||||
case VK_ERROR_EXTENSION_NOT_PRESENT:
|
||||
return "VK_ERROR_EXTENSION_NOT_PRESENT";
|
||||
case VK_ERROR_FEATURE_NOT_PRESENT:
|
||||
return "VK_ERROR_FEATURE_NOT_PRESENT";
|
||||
case VK_ERROR_INCOMPATIBLE_DRIVER:
|
||||
return "VK_ERROR_INCOMPATIBLE_DRIVER";
|
||||
case VK_ERROR_TOO_MANY_OBJECTS:
|
||||
return "VK_ERROR_TOO_MANY_OBJECTS";
|
||||
case VK_ERROR_FORMAT_NOT_SUPPORTED:
|
||||
return "VK_ERROR_FORMAT_NOT_SUPPORTED";
|
||||
case VK_ERROR_FRAGMENTED_POOL:
|
||||
return "VK_ERROR_FRAGMENTED_POOL";
|
||||
case VK_ERROR_SURFACE_LOST_KHR:
|
||||
return "VK_ERROR_SURFACE_LOST_KHR";
|
||||
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
|
||||
return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
|
||||
case VK_SUBOPTIMAL_KHR:
|
||||
return "VK_SUBOPTIMAL_KHR";
|
||||
case VK_ERROR_OUT_OF_DATE_KHR:
|
||||
return "VK_ERROR_OUT_OF_DATE_KHR";
|
||||
case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
|
||||
return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
|
||||
case VK_ERROR_VALIDATION_FAILED_EXT:
|
||||
return "VK_ERROR_VALIDATION_FAILED_EXT";
|
||||
case VK_ERROR_OUT_OF_POOL_MEMORY_KHR:
|
||||
return "VK_ERROR_OUT_OF_POOL_MEMORY_KHR";
|
||||
case VK_ERROR_INVALID_SHADER_NV:
|
||||
return "VK_ERROR_INVALID_SHADER_NV";
|
||||
case VK_RESULT_MAX_ENUM:
|
||||
case VK_RESULT_RANGE_SIZE:
|
||||
break;
|
||||
}
|
||||
if(result < 0)
|
||||
return "VK_ERROR_<Unknown>";
|
||||
return "VK_<Unknown>";
|
||||
}
|
||||
|
||||
VkExtensionProperties *SDL_Vulkan_CreateInstanceExtensionsList(
|
||||
PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties,
|
||||
Uint32 *extensionCount)
|
||||
{
|
||||
Uint32 count = 0;
|
||||
VkResult result = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
|
||||
VkExtensionProperties *retval;
|
||||
if(result == VK_ERROR_INCOMPATIBLE_DRIVER)
|
||||
{
|
||||
SDL_SetError(
|
||||
"You probably don't have a working Vulkan driver installed: getting Vulkan "
|
||||
"extensions failed: vkEnumerateInstanceExtensionProperties returned %s(%d)",
|
||||
SDL_Vulkan_GetResultString(result),
|
||||
(int)result);
|
||||
return NULL;
|
||||
}
|
||||
else if(result != VK_SUCCESS)
|
||||
{
|
||||
SDL_SetError(
|
||||
"Getting Vulkan extensions failed: vkEnumerateInstanceExtensionProperties returned "
|
||||
"%s(%d)",
|
||||
SDL_Vulkan_GetResultString(result),
|
||||
(int)result);
|
||||
return NULL;
|
||||
}
|
||||
if(count == 0)
|
||||
{
|
||||
retval = SDL_calloc(1, sizeof(VkExtensionProperties)); // so we can return non-null
|
||||
if(!retval)
|
||||
{
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
*extensionCount = 0;
|
||||
}
|
||||
retval = SDL_calloc(count, sizeof(VkExtensionProperties));
|
||||
if(!retval)
|
||||
{
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
result = vkEnumerateInstanceExtensionProperties(NULL, &count, retval);
|
||||
if(result != VK_SUCCESS)
|
||||
{
|
||||
SDL_SetError(
|
||||
"Getting Vulkan extensions failed: vkEnumerateInstanceExtensionProperties returned "
|
||||
"%s(%d)",
|
||||
SDL_Vulkan_GetResultString(result),
|
||||
(int)result);
|
||||
SDL_free(retval);
|
||||
return NULL;
|
||||
}
|
||||
*extensionCount = count;
|
||||
return retval;
|
||||
}
|
||||
|
||||
SDL_bool SDL_Vulkan_GetInstanceExtensions_Helper(unsigned *userCount,
|
||||
const char **userNames,
|
||||
unsigned nameCount,
|
||||
const char *const *names)
|
||||
{
|
||||
if(userNames)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if(*userCount != nameCount)
|
||||
{
|
||||
SDL_SetError(
|
||||
"Count doesn't match count from previous call of SDL_Vulkan_GetInstanceExtensions");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
for(i = 0; i < nameCount; i++)
|
||||
{
|
||||
userNames[i] = names[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*userCount = nameCount;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
#endif
|
@@ -40,6 +40,7 @@
|
||||
#include "SDL_androidmouse.h"
|
||||
#include "SDL_androidtouch.h"
|
||||
#include "SDL_androidwindow.h"
|
||||
#include "SDL_androidvulkan.h"
|
||||
|
||||
#define ANDROID_VID_DRIVER_NAME "Android"
|
||||
|
||||
@@ -132,6 +133,13 @@ Android_CreateDevice(int devindex)
|
||||
device->GL_SwapWindow = Android_GLES_SwapWindow;
|
||||
device->GL_DeleteContext = Android_GLES_DeleteContext;
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE
|
||||
device->Vulkan_LoadLibrary = Android_Vulkan_LoadLibrary;
|
||||
device->Vulkan_UnloadLibrary = Android_Vulkan_UnloadLibrary;
|
||||
device->Vulkan_GetInstanceExtensions = Android_Vulkan_GetInstanceExtensions;
|
||||
device->Vulkan_CreateSurface = Android_Vulkan_CreateSurface;
|
||||
#endif
|
||||
|
||||
/* Screensaver */
|
||||
device->SuspendScreenSaver = Android_SuspendScreenSaver;
|
||||
|
||||
|
174
src/video/android/SDL_androidvulkan.c
Normal file
174
src/video/android/SDL_androidvulkan.c
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
|
||||
* SDL_x11vulkan.c.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE && SDL_VIDEO_DRIVER_ANDROID
|
||||
|
||||
#include "SDL_androidvideo.h"
|
||||
#include "SDL_androidwindow.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
#include "SDL_androidvulkan.h"
|
||||
#include "SDL_syswm.h"
|
||||
|
||||
int Android_Vulkan_LoadLibrary(_THIS, const char *path)
|
||||
{
|
||||
VkExtensionProperties *extensions = NULL;
|
||||
Uint32 extensionCount = 0;
|
||||
SDL_bool hasSurfaceExtension = SDL_FALSE;
|
||||
SDL_bool hasAndroidSurfaceExtension = SDL_FALSE;
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
|
||||
if(_this->vulkan_config.loader_handle)
|
||||
return SDL_SetError("Vulkan already loaded");
|
||||
|
||||
/* Load the Vulkan loader library */
|
||||
if(!path)
|
||||
path = SDL_getenv("SDL_VULKAN_LIBRARY");
|
||||
if(!path)
|
||||
path = "libvulkan.so.1";
|
||||
_this->vulkan_config.loader_handle = SDL_LoadObject(path);
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
return -1;
|
||||
SDL_strlcpy(_this->vulkan_config.loader_path, path,
|
||||
SDL_arraysize(_this->vulkan_config.loader_path));
|
||||
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
|
||||
_this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
|
||||
if(!vkGetInstanceProcAddr)
|
||||
goto fail;
|
||||
_this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties =
|
||||
(void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)(
|
||||
VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
|
||||
if(!_this->vulkan_config.vkEnumerateInstanceExtensionProperties)
|
||||
goto fail;
|
||||
extensions = SDL_Vulkan_CreateInstanceExtensionsList(
|
||||
(PFN_vkEnumerateInstanceExtensionProperties)
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties,
|
||||
&extensionCount);
|
||||
if(!extensions)
|
||||
goto fail;
|
||||
for(Uint32 i = 0; i < extensionCount; i++)
|
||||
{
|
||||
if(SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
|
||||
hasSurfaceExtension = SDL_TRUE;
|
||||
else if(SDL_strcmp(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
|
||||
hasAndroidSurfaceExtension = SDL_TRUE;
|
||||
}
|
||||
SDL_free(extensions);
|
||||
if(!hasSurfaceExtension)
|
||||
{
|
||||
SDL_SetError("Installed Vulkan doesn't implement the "
|
||||
VK_KHR_SURFACE_EXTENSION_NAME " extension");
|
||||
goto fail;
|
||||
}
|
||||
else if(!hasAndroidSurfaceExtension)
|
||||
{
|
||||
SDL_SetError("Installed Vulkan doesn't implement the "
|
||||
VK_KHR_ANDROID_SURFACE_EXTENSION_NAME "extension");
|
||||
goto fail;
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Android_Vulkan_UnloadLibrary(_THIS)
|
||||
{
|
||||
if(_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool Android_Vulkan_GetInstanceExtensions(_THIS,
|
||||
SDL_Window *window,
|
||||
unsigned *count,
|
||||
const char **names)
|
||||
{
|
||||
static const char *const extensionsForAndroid[] = {
|
||||
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME
|
||||
};
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_Vulkan_GetInstanceExtensions_Helper(
|
||||
count, names, SDL_arraysize(extensionsForMir),
|
||||
extensionsForAndroid);
|
||||
}
|
||||
|
||||
SDL_bool Android_Vulkan_CreateSurface(_THIS,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface)
|
||||
{
|
||||
SDL_WindowData *windowData = (SDL_WindowData *)window->driverdata;
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
|
||||
(PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
|
||||
PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR =
|
||||
(PFN_vkCreateAndroidSurfaceKHR)vkGetInstanceProcAddr(
|
||||
(VkInstance)instance,
|
||||
"vkCreateAndroidSurfaceKHR");
|
||||
VkAndroidSurfaceCreateInfoKHR createInfo = {};
|
||||
VkResult result;
|
||||
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if(!vkCreateAndroidSurfaceKHR)
|
||||
{
|
||||
SDL_SetError(VK_KHR_Android_SURFACE_EXTENSION_NAME
|
||||
" extension is not enabled in the Vulkan instance.");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_Android_SURFACE_CREATE_INFO_KHR;
|
||||
createInfo.pNext = NULL;
|
||||
createInfo.flags = 0;
|
||||
createInfo.window = windowData->native_window;
|
||||
result = vkCreateAndroidSurfaceKHR(instance, &createInfo,
|
||||
NULL, surface);
|
||||
if(result != VK_SUCCESS)
|
||||
{
|
||||
SDL_SetError("vkCreateAndroidSurfaceKHR failed: %s",
|
||||
SDL_Vulkan_GetResultString(result));
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
52
src/video/android/SDL_androidvulkan.h
Normal file
52
src/video/android/SDL_androidvulkan.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
|
||||
* SDL_x11vulkan.h.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef _SDL_androidvulkan_h
|
||||
#define _SDL_androidvulkan_h
|
||||
|
||||
#include "../SDL_vulkan_internal.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE && SDL_VIDEO_DRIVER_ANDROID
|
||||
|
||||
int Android_Vulkan_LoadLibrary(_THIS, const char *path);
|
||||
void Android_Vulkan_UnloadLibrary(_THIS);
|
||||
SDL_bool Android_Vulkan_GetInstanceExtensions(_THIS,
|
||||
SDL_Window *window,
|
||||
unsigned *count,
|
||||
const char **names);
|
||||
SDL_bool Android_Vulkan_CreateSurface(_THIS,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _SDL_androidvulkan_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
61
src/video/cocoa/SDL_cocoametalview.h
Normal file
61
src/video/cocoa/SDL_cocoametalview.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2017 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com.
|
||||
*
|
||||
* Thanks to Alex Szpakowski, @slime73 on GitHub, for his gist showing
|
||||
* how to add a CAMetalLayer backed view.
|
||||
*/
|
||||
|
||||
#ifndef _SDL_cocoametalview_h
|
||||
#define _SDL_cocoametalview_h
|
||||
|
||||
#import "../SDL_sysvideo.h"
|
||||
#import "SDL_cocoawindow.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Metal/Metal.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
|
||||
#define METALVIEW_TAG 255
|
||||
|
||||
@interface SDL_cocoametalview : NSView {
|
||||
NSInteger _tag;
|
||||
bool _useHighDPI;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(NSRect)frame
|
||||
useHighDPI:(bool)useHighDPI;
|
||||
|
||||
/* Override superclass tag so this class can set it. */
|
||||
@property (assign, readonly) NSInteger tag;
|
||||
|
||||
@end
|
||||
|
||||
SDL_cocoametalview* Cocoa_Mtl_AddMetalView(SDL_Window* window);
|
||||
|
||||
void Cocoa_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h);
|
||||
|
||||
#endif /* _SDL_cocoametalview_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
124
src/video/cocoa/SDL_cocoametalview.m
Normal file
124
src/video/cocoa/SDL_cocoametalview.m
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2017 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com.
|
||||
*
|
||||
* Thanks to Alex Szpakowski, @slime73 on GitHub, for his gist showing
|
||||
* how to add a CAMetalLayer backed view.
|
||||
*/
|
||||
|
||||
/* this is (currently) only used with Vulkan. Remove this #if when that changes! */
|
||||
#if SDL_VIDEO_VULKAN_SURFACE && SDL_VIDEO_DRIVER_COCOA
|
||||
|
||||
#import "SDL_cocoametalview.h"
|
||||
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_loadso.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
@implementation SDL_cocoametalview
|
||||
|
||||
/* The synthesized getter should be called by super's viewWithTag. */
|
||||
@synthesize tag = _tag;
|
||||
|
||||
/* Return a Metal-compatible layer. */
|
||||
+ (Class)layerClass
|
||||
{
|
||||
return [CAMetalLayer class];
|
||||
}
|
||||
|
||||
/* Indicate the view wants to draw using a backing layer instead of drawRect. */
|
||||
-(BOOL) wantsUpdateLayer { return YES; }
|
||||
|
||||
/* When the wantsLayer property is set to YES, this method will be invoked to
|
||||
* return a layer instance.
|
||||
*/
|
||||
-(CALayer*) makeBackingLayer { return [self.class.layerClass layer]; }
|
||||
|
||||
- (instancetype)initWithFrame:(NSRect)frame
|
||||
useHighDPI:(bool)useHighDPI
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
|
||||
/* Allow resize. */
|
||||
self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
_tag = METALVIEW_TAG;
|
||||
|
||||
_useHighDPI = useHighDPI;
|
||||
[self updateDrawableSize];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Set the size of the metal drawables when the view is resized. */
|
||||
- (void)resizeSubviewsWithOldSize:(NSSize)oldSize {
|
||||
[super resizeSubviewsWithOldSize:oldSize];
|
||||
[self updateDrawableSize];
|
||||
}
|
||||
|
||||
- (void)updateDrawableSize
|
||||
{
|
||||
if (_useHighDPI) {
|
||||
NSSize size = [self convertRectToBacking:[self bounds]].size;
|
||||
/* Isn't there a better way to convert from NSSize to CGSize? */
|
||||
CGSize cgsize = *(CGSize*)&size;
|
||||
((CAMetalLayer *) self.layer).drawableSize = cgsize;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
SDL_cocoametalview*
|
||||
Cocoa_Mtl_AddMetalView(SDL_Window* window)
|
||||
{
|
||||
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
|
||||
NSView *view = data->nswindow.contentView;
|
||||
|
||||
SDL_cocoametalview *metalview
|
||||
= [[SDL_cocoametalview alloc] initWithFrame:view.frame
|
||||
useHighDPI:(window->flags & SDL_WINDOW_ALLOW_HIGHDPI)];
|
||||
[view addSubview:metalview];
|
||||
|
||||
return metalview;
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h)
|
||||
{
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
|
||||
NSView *view = data->nswindow.contentView;
|
||||
SDL_cocoametalview* metalview = [view viewWithTag:METALVIEW_TAG];
|
||||
if (metalview) {
|
||||
CAMetalLayer *layer = (CAMetalLayer*)metalview.layer;
|
||||
assert(layer != NULL);
|
||||
if (w)
|
||||
*w = layer.drawableSize.width;
|
||||
if (h)
|
||||
*h = layer.drawableSize.height;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_cocoavideo.h"
|
||||
#include "SDL_cocoashape.h"
|
||||
#include "SDL_cocoavulkan.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
/* Initialization/Query functions */
|
||||
@@ -122,6 +123,14 @@ Cocoa_CreateDevice(int devindex)
|
||||
device->GL_DeleteContext = Cocoa_GL_DeleteContext;
|
||||
#endif
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE
|
||||
device->Vulkan_LoadLibrary = Cocoa_Vulkan_LoadLibrary;
|
||||
device->Vulkan_UnloadLibrary = Cocoa_Vulkan_UnloadLibrary;
|
||||
device->Vulkan_GetInstanceExtensions = Cocoa_Vulkan_GetInstanceExtensions;
|
||||
device->Vulkan_CreateSurface = Cocoa_Vulkan_CreateSurface;
|
||||
device->Vulkan_GetDrawableSize = Cocoa_Vulkan_GetDrawableSize;
|
||||
#endif
|
||||
|
||||
device->StartTextInput = Cocoa_StartTextInput;
|
||||
device->StopTextInput = Cocoa_StopTextInput;
|
||||
device->SetTextInputRect = Cocoa_SetTextInputRect;
|
||||
|
55
src/video/cocoa/SDL_cocoavulkan.h
Normal file
55
src/video/cocoa/SDL_cocoavulkan.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
|
||||
* SDL_x11vulkan.h.
|
||||
*/
|
||||
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef _SDL_cocoavulkan_h
|
||||
#define _SDL_cocoavulkan_h
|
||||
|
||||
#include "../SDL_vulkan_internal.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE && SDL_VIDEO_DRIVER_COCOA
|
||||
|
||||
int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path);
|
||||
void Cocoa_Vulkan_UnloadLibrary(_THIS);
|
||||
SDL_bool Cocoa_Vulkan_GetInstanceExtensions(_THIS,
|
||||
SDL_Window *window,
|
||||
unsigned *count,
|
||||
const char **names);
|
||||
SDL_bool Cocoa_Vulkan_CreateSurface(_THIS,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface);
|
||||
|
||||
void Cocoa_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _SDL_cocoavulkan_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
217
src/video/cocoa/SDL_cocoavulkan.m
Normal file
217
src/video/cocoa/SDL_cocoavulkan.m
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
|
||||
* SDL_x11vulkan.c.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE && SDL_VIDEO_DRIVER_COCOA
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
#include "SDL_cocoawindow.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
#include "SDL_cocoametalview.h"
|
||||
#include "SDL_cocoavulkan.h"
|
||||
#include "SDL_syswm.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define DEFAULT_MOLTENVK "libMoltenVK.dylib"
|
||||
/* Since libSDL is most likely a .dylib, need RTLD_DEFAULT not RTLD_SELF. */
|
||||
#define DEFAULT_HANDLE RTLD_DEFAULT
|
||||
|
||||
int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path)
|
||||
{
|
||||
VkExtensionProperties *extensions = NULL;
|
||||
Uint32 extensionCount = 0;
|
||||
SDL_bool hasSurfaceExtension = SDL_FALSE;
|
||||
SDL_bool hasMacOSSurfaceExtension = SDL_FALSE;
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
|
||||
if(_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_SetError("MoltenVK/Vulkan already loaded");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Load the Vulkan loader library */
|
||||
if(!path)
|
||||
path = SDL_getenv("SDL_VULKAN_LIBRARY");
|
||||
if(!path)
|
||||
{
|
||||
/* MoltenVK framework, currently, v0.17.0, has a static library and is
|
||||
* the recommended way to use the package. There is likely no object to
|
||||
* load. */
|
||||
vkGetInstanceProcAddr =
|
||||
(PFN_vkGetInstanceProcAddr)dlsym(DEFAULT_HANDLE,
|
||||
"vkGetInstanceProcAddr");
|
||||
}
|
||||
|
||||
if(vkGetInstanceProcAddr)
|
||||
{
|
||||
_this->vulkan_config.loader_handle = DEFAULT_HANDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!path)
|
||||
{
|
||||
/* Look for the .dylib packaged with the application instead. */
|
||||
path = DEFAULT_MOLTENVK;
|
||||
}
|
||||
|
||||
_this->vulkan_config.loader_handle = SDL_LoadObject(path);
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
return -1;
|
||||
SDL_strlcpy(_this->vulkan_config.loader_path, path,
|
||||
SDL_arraysize(_this->vulkan_config.loader_path));
|
||||
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
|
||||
_this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
|
||||
}
|
||||
if(!vkGetInstanceProcAddr)
|
||||
{
|
||||
SDL_SetError("Failed to find %s in either executable or %s: %s",
|
||||
"vkGetInstanceProcAddr",
|
||||
DEFAULT_MOLTENVK,
|
||||
(const char *) dlerror());
|
||||
goto fail;
|
||||
}
|
||||
|
||||
_this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties =
|
||||
(void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)(
|
||||
VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
|
||||
if(!_this->vulkan_config.vkEnumerateInstanceExtensionProperties)
|
||||
goto fail;
|
||||
extensions = SDL_Vulkan_CreateInstanceExtensionsList(
|
||||
(PFN_vkEnumerateInstanceExtensionProperties)
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties,
|
||||
&extensionCount);
|
||||
if(!extensions)
|
||||
goto fail;
|
||||
for(Uint32 i = 0; i < extensionCount; i++)
|
||||
{
|
||||
if(SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
|
||||
hasSurfaceExtension = SDL_TRUE;
|
||||
else if(SDL_strcmp(VK_MVK_MACOS_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
|
||||
hasMacOSSurfaceExtension = SDL_TRUE;
|
||||
}
|
||||
SDL_free(extensions);
|
||||
if(!hasSurfaceExtension)
|
||||
{
|
||||
SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
|
||||
VK_KHR_SURFACE_EXTENSION_NAME " extension");
|
||||
goto fail;
|
||||
}
|
||||
else if(!hasMacOSSurfaceExtension)
|
||||
{
|
||||
SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
|
||||
VK_MVK_MACOS_SURFACE_EXTENSION_NAME "extension");
|
||||
goto fail;
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Cocoa_Vulkan_UnloadLibrary(_THIS)
|
||||
{
|
||||
if(_this->vulkan_config.loader_handle)
|
||||
{
|
||||
if (_this->vulkan_config.loader_handle != DEFAULT_HANDLE)
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool Cocoa_Vulkan_GetInstanceExtensions(_THIS,
|
||||
SDL_Window *window,
|
||||
unsigned *count,
|
||||
const char **names)
|
||||
{
|
||||
static const char *const extensionsForCocoa[] = {
|
||||
VK_KHR_SURFACE_EXTENSION_NAME, VK_MVK_MACOS_SURFACE_EXTENSION_NAME
|
||||
};
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_Vulkan_GetInstanceExtensions_Helper(
|
||||
count, names, SDL_arraysize(extensionsForCocoa),
|
||||
extensionsForCocoa);
|
||||
}
|
||||
|
||||
SDL_bool Cocoa_Vulkan_CreateSurface(_THIS,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface)
|
||||
{
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
|
||||
(PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
|
||||
PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK =
|
||||
(PFN_vkCreateMacOSSurfaceMVK)vkGetInstanceProcAddr(
|
||||
(VkInstance)instance,
|
||||
"vkCreateMacOSSurfaceMVK");
|
||||
VkMacOSSurfaceCreateInfoMVK createInfo = {};
|
||||
VkResult result;
|
||||
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if(!vkCreateMacOSSurfaceMVK)
|
||||
{
|
||||
SDL_SetError(VK_MVK_MACOS_SURFACE_EXTENSION_NAME
|
||||
" extension is not enabled in the Vulkan instance.");
|
||||
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);
|
||||
result = vkCreateMacOSSurfaceMVK(instance, &createInfo,
|
||||
NULL, surface);
|
||||
if(result != VK_SUCCESS)
|
||||
{
|
||||
SDL_SetError("vkCreateMacOSSurfaceMVK failed: %s",
|
||||
SDL_Vulkan_GetResultString(result));
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
void Cocoa_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
|
||||
{
|
||||
Cocoa_Mtl_GetDrawableSize(window, w, h);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* vim: set ts=4 sw=4 expandtab: */
|
@@ -36,6 +36,7 @@
|
||||
#include "SDL_mirmouse.h"
|
||||
#include "SDL_miropengl.h"
|
||||
#include "SDL_mirvideo.h"
|
||||
#include "SDL_mirvulkan.h"
|
||||
|
||||
#include "SDL_mirdyn.h"
|
||||
|
||||
@@ -232,6 +233,13 @@ MIR_CreateDevice(int device_index)
|
||||
|
||||
device->ShowMessageBox = NULL;
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE
|
||||
device->Vulkan_LoadLibrary = MIR_Vulkan_LoadLibrary;
|
||||
device->Vulkan_UnloadLibrary = MIR_Vulkan_UnloadLibrary;
|
||||
device->Vulkan_GetInstanceExtensions = MIR_Vulkan_GetInstanceExtensions;
|
||||
device->Vulkan_CreateSurface = MIR_Vulkan_CreateSurface;
|
||||
#endif
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
|
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <mir_toolkit/mir_client_library.h>
|
||||
#include "SDL_stdinc.h"
|
||||
|
||||
typedef struct MIR_Window MIR_Window;
|
||||
|
||||
|
175
src/video/mir/SDL_mirvulkan.c
Normal file
175
src/video/mir/SDL_mirvulkan.c
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
|
||||
* SDL_x11vulkan.c.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE && SDL_VIDEO_DRIVER_MIR
|
||||
|
||||
#include "SDL_mirvideo.h"
|
||||
#include "SDL_mirwindow.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
#include "SDL_mirvulkan.h"
|
||||
#include "SDL_syswm.h"
|
||||
|
||||
int MIR_Vulkan_LoadLibrary(_THIS, const char *path)
|
||||
{
|
||||
VkExtensionProperties *extensions = NULL;
|
||||
Uint32 extensionCount = 0;
|
||||
SDL_bool hasSurfaceExtension = SDL_FALSE;
|
||||
SDL_bool hasMIRSurfaceExtension = SDL_FALSE;
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
|
||||
if(_this->vulkan_config.loader_handle)
|
||||
return SDL_SetError("Vulkan already loaded");
|
||||
|
||||
/* Load the Vulkan loader library */
|
||||
if(!path)
|
||||
path = SDL_getenv("SDL_VULKAN_LIBRARY");
|
||||
if(!path)
|
||||
path = "libvulkan.so.1";
|
||||
_this->vulkan_config.loader_handle = SDL_LoadObject(path);
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
return -1;
|
||||
SDL_strlcpy(_this->vulkan_config.loader_path, path,
|
||||
SDL_arraysize(_this->vulkan_config.loader_path));
|
||||
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
|
||||
_this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
|
||||
if(!vkGetInstanceProcAddr)
|
||||
goto fail;
|
||||
_this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties =
|
||||
(void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)(
|
||||
VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
|
||||
if(!_this->vulkan_config.vkEnumerateInstanceExtensionProperties)
|
||||
goto fail;
|
||||
extensions = SDL_Vulkan_CreateInstanceExtensionsList(
|
||||
(PFN_vkEnumerateInstanceExtensionProperties)
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties,
|
||||
&extensionCount);
|
||||
if(!extensions)
|
||||
goto fail;
|
||||
for(Uint32 i = 0; i < extensionCount; i++)
|
||||
{
|
||||
if(SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
|
||||
hasSurfaceExtension = SDL_TRUE;
|
||||
else if(SDL_strcmp(VK_KHR_MIR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
|
||||
hasMIRSurfaceExtension = SDL_TRUE;
|
||||
}
|
||||
SDL_free(extensions);
|
||||
if(!hasSurfaceExtension)
|
||||
{
|
||||
SDL_SetError("Installed Vulkan doesn't implement the "
|
||||
VK_KHR_SURFACE_EXTENSION_NAME " extension");
|
||||
goto fail;
|
||||
}
|
||||
else if(!hasMIRSurfaceExtension)
|
||||
{
|
||||
SDL_SetError("Installed Vulkan doesn't implement the "
|
||||
VK_KHR_MIR_SURFACE_EXTENSION_NAME "extension");
|
||||
goto fail;
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void MIR_Vulkan_UnloadLibrary(_THIS)
|
||||
{
|
||||
if(_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool MIR_Vulkan_GetInstanceExtensions(_THIS,
|
||||
SDL_Window *window,
|
||||
unsigned *count,
|
||||
const char **names)
|
||||
{
|
||||
static const char *const extensionsForMir[] = {
|
||||
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_MIR_SURFACE_EXTENSION_NAME
|
||||
};
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_Vulkan_GetInstanceExtensions_Helper(
|
||||
count, names, SDL_arraysize(extensionsForMir),
|
||||
extensionsForMir);
|
||||
}
|
||||
|
||||
SDL_bool MIR_Vulkan_CreateSurface(_THIS,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface)
|
||||
{
|
||||
MIR_Window *windowData = (MIR_Window *)window->driverdata;
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
|
||||
(PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
|
||||
PFN_vkCreateMirSurfaceKHR vkCreateMirSurfaceKHR =
|
||||
(PFN_vkCreateMirSurfaceKHR)vkGetInstanceProcAddr(
|
||||
(VkInstance)instance,
|
||||
"vkCreateMirSurfaceKHR");
|
||||
VkMirSurfaceCreateInfoKHR createInfo = {};
|
||||
VkResult result;
|
||||
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if(!vkCreateMirSurfaceKHR)
|
||||
{
|
||||
SDL_SetError(VK_KHR_MIR_SURFACE_EXTENSION_NAME
|
||||
" extension is not enabled in the Vulkan instance.");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR;
|
||||
createInfo.pNext = NULL;
|
||||
createInfo.flags = 0;
|
||||
createInfo.connection = windowData->mir_data->connection;
|
||||
createInfo.mirSurface = windowData->window;
|
||||
result = vkCreateMirSurfaceKHR(instance, &createInfo,
|
||||
NULL, surface);
|
||||
if(result != VK_SUCCESS)
|
||||
{
|
||||
SDL_SetError("vkCreateMirSurfaceKHR failed: %s",
|
||||
SDL_Vulkan_GetResultString(result));
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* vim: set ts=4 sw=4 expandtab: */
|
52
src/video/mir/SDL_mirvulkan.h
Normal file
52
src/video/mir/SDL_mirvulkan.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
|
||||
* SDL_x11vulkan.h.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef _SDL_mirvulkan_h
|
||||
#define _SDL_mirvulkan_h
|
||||
|
||||
#include "../SDL_vulkan_internal.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE && SDL_VIDEO_DRIVER_MIR
|
||||
|
||||
int MIR_Vulkan_LoadLibrary(_THIS, const char *path);
|
||||
void MIR_Vulkan_UnloadLibrary(_THIS);
|
||||
SDL_bool MIR_Vulkan_GetInstanceExtensions(_THIS,
|
||||
SDL_Window *window,
|
||||
unsigned *count,
|
||||
const char **names);
|
||||
SDL_bool MIR_Vulkan_CreateSurface(_THIS,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _SDL_mirvulkan_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
53
src/video/uikit/SDL_uikitmetalview.h
Normal file
53
src/video/uikit/SDL_uikitmetalview.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2017 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com.
|
||||
*
|
||||
* Thanks to Alex Szpakowski, @slime73 on GitHub, for his gist showing
|
||||
* how to add a CAMetalLayer backed view.
|
||||
*/
|
||||
|
||||
#ifndef _SDL_uikitmetalview_h
|
||||
#define _SDL_uikitmetalview_h
|
||||
|
||||
#import "../SDL_sysvideo.h"
|
||||
#import "SDL_uikitwindow.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Metal/Metal.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
|
||||
#define METALVIEW_TAG 255
|
||||
|
||||
@interface SDL_uikitmetalview : UIView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
scale:(CGFloat)scale
|
||||
tag:(int)tag;
|
||||
|
||||
@end
|
||||
|
||||
SDL_uikitmetalview* UIKit_Mtl_AddMetalView(SDL_Window* window);
|
||||
|
||||
void UIKit_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h);
|
||||
|
||||
#endif /* _SDL_uikitmetalview_h */
|
146
src/video/uikit/SDL_uikitmetalview.m
Normal file
146
src/video/uikit/SDL_uikitmetalview.m
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2017 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com.
|
||||
*
|
||||
* Thanks to Alex Szpakowski, @slime73 on GitHub, for his gist showing
|
||||
* how to add a CAMetalLayer backed view.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE && SDL_VIDEO_DRIVER_UIKIT
|
||||
|
||||
#import "../SDL_sysvideo.h"
|
||||
#import "SDL_uikitwindow.h"
|
||||
#import "SDL_uikitmetalview.h"
|
||||
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_loadso.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
static void* loader_handle;
|
||||
|
||||
@implementation SDL_uikitmetalview
|
||||
|
||||
/* Returns a Metal-compatible layer. */
|
||||
+ (Class)layerClass
|
||||
{
|
||||
return [CAMetalLayer class];
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
scale:(CGFloat)scale
|
||||
tag:(int)tag
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
/* Resize properly when rotated. */
|
||||
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
|
||||
/* Set the appropriate scale (for retina display support) */
|
||||
self.contentScaleFactor = scale;
|
||||
self.tag = tag;
|
||||
|
||||
[self updateDrawableSize];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Set the size of the metal drawables when the view is resized. */
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
[self updateDrawableSize];
|
||||
}
|
||||
|
||||
- (void)updateDrawableSize
|
||||
{
|
||||
CGSize size = self.bounds.size;
|
||||
size.width *= self.contentScaleFactor;
|
||||
size.height *= self.contentScaleFactor;
|
||||
|
||||
((CAMetalLayer *) self.layer).drawableSize = size;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
SDL_uikitmetalview*
|
||||
UIKit_Mtl_AddMetalView(SDL_Window* window)
|
||||
{
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
|
||||
SDL_uikitview *view = (SDL_uikitview*)data.uiwindow.rootViewController.view;
|
||||
CGFloat scale = 1.0;
|
||||
|
||||
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
|
||||
/* Set the scale to the natural scale factor of the screen - the
|
||||
* backing dimensions of the Metal view will match the pixel
|
||||
* dimensions of the screen rather than the dimensions in points.
|
||||
*/
|
||||
#ifdef __IPHONE_8_0
|
||||
if ([data.uiwindow.screen respondsToSelector:@selector(nativeScale)]) {
|
||||
scale = data.uiwindow.screen.nativeScale;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
scale = data.uiwindow.screen.scale;
|
||||
}
|
||||
}
|
||||
SDL_uikitmetalview *metalview
|
||||
= [[SDL_uikitmetalview alloc] initWithFrame:view.frame
|
||||
scale:scale
|
||||
tag:METALVIEW_TAG];
|
||||
#if 1
|
||||
[view addSubview:metalview];
|
||||
#else
|
||||
/* Sets this view as the controller's view, and adds the view to
|
||||
* the window hierarchy.
|
||||
*
|
||||
* Left here for information. Not used because I suspect that for correct
|
||||
* operation it will be necesary to copy everything from the window's
|
||||
* current SDL_uikitview instance to the SDL_uikitview portion of the
|
||||
* SDL_metalview. The latter would be derived from SDL_uikitview rather
|
||||
* than UIView. */
|
||||
[metalview setSDLWindow:window];
|
||||
#endif
|
||||
|
||||
return metalview;
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h)
|
||||
{
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
|
||||
SDL_uikitview *view = (SDL_uikitview*)data.uiwindow.rootViewController.view;
|
||||
SDL_uikitmetalview* metalview = [view viewWithTag:METALVIEW_TAG];
|
||||
if (metalview) {
|
||||
CAMetalLayer *layer = (CAMetalLayer*)metalview.layer;
|
||||
assert(layer != NULL);
|
||||
if (w)
|
||||
*w = layer.drawableSize.width;
|
||||
if (h)
|
||||
*h = layer.drawableSize.height;
|
||||
} else
|
||||
SDL_GetWindowSize(window, w, h);
|
||||
}
|
||||
|
||||
#endif
|
@@ -37,6 +37,7 @@
|
||||
#include "SDL_uikitwindow.h"
|
||||
#include "SDL_uikitopengles.h"
|
||||
#include "SDL_uikitclipboard.h"
|
||||
#include "SDL_uikitvulkan.h"
|
||||
|
||||
#define UIKITVID_DRIVER_NAME "uikit"
|
||||
|
||||
@@ -123,6 +124,15 @@ UIKit_CreateDevice(int devindex)
|
||||
device->GL_LoadLibrary = UIKit_GL_LoadLibrary;
|
||||
device->free = UIKit_DeleteDevice;
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE
|
||||
device->Vulkan_LoadLibrary = UIKit_Vulkan_LoadLibrary;
|
||||
device->Vulkan_UnloadLibrary = UIKit_Vulkan_UnloadLibrary;
|
||||
device->Vulkan_GetInstanceExtensions
|
||||
= UIKit_Vulkan_GetInstanceExtensions;
|
||||
device->Vulkan_CreateSurface = UIKit_Vulkan_CreateSurface;
|
||||
device->Vulkan_GetDrawableSize = UIKit_Vulkan_GetDrawableSize;
|
||||
#endif
|
||||
|
||||
device->gl_config.accelerated = 1;
|
||||
|
||||
return device;
|
||||
|
54
src/video/uikit/SDL_uikitvulkan.h
Normal file
54
src/video/uikit/SDL_uikitvulkan.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
|
||||
* SDL_x11vulkan.h.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef _SDL_uikitvulkan_h
|
||||
#define _SDL_uikitvulkan_h
|
||||
|
||||
#include "../SDL_vulkan_internal.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE && SDL_VIDEO_DRIVER_UIKIT
|
||||
|
||||
int UIKit_Vulkan_LoadLibrary(_THIS, const char *path);
|
||||
void UIKit_Vulkan_UnloadLibrary(_THIS);
|
||||
SDL_bool UIKit_Vulkan_GetInstanceExtensions(_THIS,
|
||||
SDL_Window *window,
|
||||
unsigned *count,
|
||||
const char **names);
|
||||
SDL_bool UIKit_Vulkan_CreateSurface(_THIS,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface);
|
||||
|
||||
void UIKit_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _SDL_uikitvulkan_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
221
src/video/uikit/SDL_uikitvulkan.m
Normal file
221
src/video/uikit/SDL_uikitvulkan.m
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
|
||||
* SDL_x11vulkan.c.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE && SDL_VIDEO_DRIVER_UIKIT
|
||||
|
||||
#include "SDL_uikitvideo.h"
|
||||
#include "SDL_uikitwindow.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
#include "SDL_uikitvulkan.h"
|
||||
#include "SDL_uikitmetalview.h"
|
||||
#include "SDL_syswm.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define DEFAULT_MOLTENVK "libMoltenVK.dylib"
|
||||
/* Since libSDL is static, could use RTLD_SELF. Using RTLD_DEFAULT is future
|
||||
* proofing. */
|
||||
#define DEFAULT_HANDLE RTLD_DEFAULT
|
||||
|
||||
int UIKit_Vulkan_LoadLibrary(_THIS, const char *path)
|
||||
{
|
||||
VkExtensionProperties *extensions = NULL;
|
||||
Uint32 extensionCount = 0;
|
||||
SDL_bool hasSurfaceExtension = SDL_FALSE;
|
||||
SDL_bool hasIOSSurfaceExtension = SDL_FALSE;
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
|
||||
|
||||
if(_this->vulkan_config.loader_handle)
|
||||
return SDL_SetError("MoltenVK/Vulkan already loaded");
|
||||
|
||||
/* Load the Vulkan loader library */
|
||||
if(!path)
|
||||
path = SDL_getenv("SDL_VULKAN_LIBRARY");
|
||||
if(!path)
|
||||
{
|
||||
/* MoltenVK framework, currently, v0.17.0, has a static library and is
|
||||
* the recommended way to use the package. There is likely no object to
|
||||
* load. */
|
||||
vkGetInstanceProcAddr =
|
||||
(PFN_vkGetInstanceProcAddr)dlsym(DEFAULT_HANDLE,
|
||||
"vkGetInstanceProcAddr");
|
||||
}
|
||||
|
||||
if(vkGetInstanceProcAddr)
|
||||
{
|
||||
_this->vulkan_config.loader_handle = DEFAULT_HANDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!path)
|
||||
{
|
||||
/* Look for the .dylib packaged with the application instead. */
|
||||
path = DEFAULT_MOLTENVK;
|
||||
}
|
||||
|
||||
_this->vulkan_config.loader_handle = SDL_LoadObject(path);
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
return -1;
|
||||
SDL_strlcpy(_this->vulkan_config.loader_path, path,
|
||||
SDL_arraysize(_this->vulkan_config.loader_path));
|
||||
vkGetInstanceProcAddr =
|
||||
(PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
|
||||
_this->vulkan_config.loader_handle,
|
||||
"vkGetInstanceProcAddr");
|
||||
}
|
||||
if(!vkGetInstanceProcAddr)
|
||||
{
|
||||
SDL_SetError("Failed to find %s in either executable or %s: %s",
|
||||
"vkGetInstanceProcAddr",
|
||||
DEFAULT_MOLTENVK,
|
||||
(const char *) dlerror());
|
||||
goto fail;
|
||||
}
|
||||
|
||||
_this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties =
|
||||
(void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)(
|
||||
VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
|
||||
if(!_this->vulkan_config.vkEnumerateInstanceExtensionProperties)
|
||||
{
|
||||
SDL_SetError("No vkEnumerateInstanceExtensionProperties found.");
|
||||
goto fail;
|
||||
}
|
||||
extensions = SDL_Vulkan_CreateInstanceExtensionsList(
|
||||
(PFN_vkEnumerateInstanceExtensionProperties)
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties,
|
||||
&extensionCount);
|
||||
if(!extensions)
|
||||
goto fail;
|
||||
for(Uint32 i = 0; i < extensionCount; i++)
|
||||
{
|
||||
if(SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
|
||||
hasSurfaceExtension = SDL_TRUE;
|
||||
else if(SDL_strcmp(VK_MVK_IOS_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
|
||||
hasIOSSurfaceExtension = SDL_TRUE;
|
||||
}
|
||||
SDL_free(extensions);
|
||||
if(!hasSurfaceExtension)
|
||||
{
|
||||
SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
|
||||
VK_KHR_SURFACE_EXTENSION_NAME " extension");
|
||||
goto fail;
|
||||
}
|
||||
else if(!hasIOSSurfaceExtension)
|
||||
{
|
||||
SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
|
||||
VK_MVK_IOS_SURFACE_EXTENSION_NAME "extension");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void UIKit_Vulkan_UnloadLibrary(_THIS)
|
||||
{
|
||||
if(_this->vulkan_config.loader_handle)
|
||||
{
|
||||
if (_this->vulkan_config.loader_handle != DEFAULT_HANDLE)
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool UIKit_Vulkan_GetInstanceExtensions(_THIS,
|
||||
SDL_Window *window,
|
||||
unsigned *count,
|
||||
const char **names)
|
||||
{
|
||||
static const char *const extensionsForUIKit[] = {
|
||||
VK_KHR_SURFACE_EXTENSION_NAME, VK_MVK_IOS_SURFACE_EXTENSION_NAME
|
||||
};
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_Vulkan_GetInstanceExtensions_Helper(
|
||||
count, names, SDL_arraysize(extensionsForUIKit),
|
||||
extensionsForUIKit);
|
||||
}
|
||||
|
||||
SDL_bool UIKit_Vulkan_CreateSurface(_THIS,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface)
|
||||
{
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
|
||||
(PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
|
||||
PFN_vkCreateIOSSurfaceMVK vkCreateIOSSurfaceMVK =
|
||||
(PFN_vkCreateIOSSurfaceMVK)vkGetInstanceProcAddr(
|
||||
(VkInstance)instance,
|
||||
"vkCreateIOSSurfaceMVK");
|
||||
VkIOSSurfaceCreateInfoMVK createInfo = {};
|
||||
VkResult result;
|
||||
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if(!vkCreateIOSSurfaceMVK)
|
||||
{
|
||||
SDL_SetError(VK_MVK_IOS_SURFACE_EXTENSION_NAME
|
||||
" extension is not enabled in the Vulkan instance.");
|
||||
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);
|
||||
result = vkCreateIOSSurfaceMVK(instance, &createInfo,
|
||||
NULL, surface);
|
||||
if(result != VK_SUCCESS)
|
||||
{
|
||||
SDL_SetError("vkCreateIOSSurfaceMVK failed: %s",
|
||||
SDL_Vulkan_GetResultString(result));
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
void UIKit_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
|
||||
{
|
||||
UIKit_Mtl_GetDrawableSize(window, w, h);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
@@ -35,6 +35,7 @@
|
||||
#include "SDL_waylandmouse.h"
|
||||
#include "SDL_waylandtouch.h"
|
||||
#include "SDL_waylandclipboard.h"
|
||||
#include "SDL_waylandvulkan.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
@@ -181,6 +182,13 @@ Wayland_CreateDevice(int devindex)
|
||||
device->GetClipboardText = Wayland_GetClipboardText;
|
||||
device->HasClipboardText = Wayland_HasClipboardText;
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE
|
||||
device->Vulkan_LoadLibrary = Wayland_Vulkan_LoadLibrary;
|
||||
device->Vulkan_UnloadLibrary = Wayland_Vulkan_UnloadLibrary;
|
||||
device->Vulkan_GetInstanceExtensions = Wayland_Vulkan_GetInstanceExtensions;
|
||||
device->Vulkan_CreateSurface = Wayland_Vulkan_CreateSurface;
|
||||
#endif
|
||||
|
||||
device->free = Wayland_DeleteDevice;
|
||||
|
||||
return device;
|
||||
|
175
src/video/wayland/SDL_waylandvulkan.c
Normal file
175
src/video/wayland/SDL_waylandvulkan.c
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
|
||||
* SDL_x11vulkan.c.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE && SDL_VIDEO_DRIVER_WAYLAND
|
||||
|
||||
#include "SDL_waylandvideo.h"
|
||||
#include "SDL_waylandwindow.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
#include "SDL_waylandvulkan.h"
|
||||
#include "SDL_syswm.h"
|
||||
|
||||
int Wayland_Vulkan_LoadLibrary(_THIS, const char *path)
|
||||
{
|
||||
VkExtensionProperties *extensions = NULL;
|
||||
Uint32 extensionCount = 0;
|
||||
SDL_bool hasSurfaceExtension = SDL_FALSE;
|
||||
SDL_bool hasWaylandSurfaceExtension = SDL_FALSE;
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
|
||||
if(_this->vulkan_config.loader_handle)
|
||||
return SDL_SetError("Vulkan already loaded");
|
||||
|
||||
/* Load the Vulkan loader library */
|
||||
if(!path)
|
||||
path = SDL_getenv("SDL_VULKAN_LIBRARY");
|
||||
if(!path)
|
||||
path = "libvulkan.so.1";
|
||||
_this->vulkan_config.loader_handle = SDL_LoadObject(path);
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
return -1;
|
||||
SDL_strlcpy(_this->vulkan_config.loader_path, path,
|
||||
SDL_arraysize(_this->vulkan_config.loader_path));
|
||||
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
|
||||
_this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
|
||||
if(!vkGetInstanceProcAddr)
|
||||
goto fail;
|
||||
_this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties =
|
||||
(void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)(
|
||||
VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
|
||||
if(!_this->vulkan_config.vkEnumerateInstanceExtensionProperties)
|
||||
goto fail;
|
||||
extensions = SDL_Vulkan_CreateInstanceExtensionsList(
|
||||
(PFN_vkEnumerateInstanceExtensionProperties)
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties,
|
||||
&extensionCount);
|
||||
if(!extensions)
|
||||
goto fail;
|
||||
for(Uint32 i = 0; i < extensionCount; i++)
|
||||
{
|
||||
if(SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
|
||||
hasSurfaceExtension = SDL_TRUE;
|
||||
else if(SDL_strcmp(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
|
||||
hasWaylandSurfaceExtension = SDL_TRUE;
|
||||
}
|
||||
SDL_free(extensions);
|
||||
if(!hasSurfaceExtension)
|
||||
{
|
||||
SDL_SetError("Installed Vulkan doesn't implement the "
|
||||
VK_KHR_SURFACE_EXTENSION_NAME " extension");
|
||||
goto fail;
|
||||
}
|
||||
else if(!hasWaylandSurfaceExtension)
|
||||
{
|
||||
SDL_SetError("Installed Vulkan doesn't implement the "
|
||||
VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "extension");
|
||||
goto fail;
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Wayland_Vulkan_UnloadLibrary(_THIS)
|
||||
{
|
||||
if(_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool Wayland_Vulkan_GetInstanceExtensions(_THIS,
|
||||
SDL_Window *window,
|
||||
unsigned *count,
|
||||
const char **names)
|
||||
{
|
||||
static const char *const extensionsForWayland[] = {
|
||||
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME
|
||||
};
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_Vulkan_GetInstanceExtensions_Helper(
|
||||
count, names, SDL_arraysize(extensionsForWayland),
|
||||
extensionsForWayland);
|
||||
}
|
||||
|
||||
SDL_bool Wayland_Vulkan_CreateSurface(_THIS,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface)
|
||||
{
|
||||
SDL_WindowData *windowData = (SDL_WindowData *)window->driverdata;
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
|
||||
(PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
|
||||
PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR =
|
||||
(PFN_vkCreateWaylandSurfaceKHR)vkGetInstanceProcAddr(
|
||||
(VkInstance)instance,
|
||||
"vkCreateWaylandSurfaceKHR");
|
||||
VkWaylandSurfaceCreateInfoKHR createInfo = {};
|
||||
VkResult result;
|
||||
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if(!vkCreateWaylandSurfaceKHR)
|
||||
{
|
||||
SDL_SetError(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME
|
||||
" extension is not enabled in the Vulkan instance.");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
|
||||
createInfo.pNext = NULL;
|
||||
createInfo.flags = 0;
|
||||
createInfo.display = windowData->waylandData->display;
|
||||
createInfo.surface = windowData->surface;
|
||||
result = vkCreateWaylandSurfaceKHR(instance, &createInfo,
|
||||
NULL, surface);
|
||||
if(result != VK_SUCCESS)
|
||||
{
|
||||
SDL_SetError("vkCreateWaylandSurfaceKHR failed: %s",
|
||||
SDL_Vulkan_GetResultString(result));
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* vim: set ts=4 sw=4 expandtab: */
|
52
src/video/wayland/SDL_waylandvulkan.h
Normal file
52
src/video/wayland/SDL_waylandvulkan.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
|
||||
* SDL_x11vulkan.h.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef _SDL_waylandvulkan_h
|
||||
#define _SDL_waylandvulkan_h
|
||||
|
||||
#include "../SDL_vulkan_internal.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE && SDL_VIDEO_DRIVER_WAYLAND
|
||||
|
||||
int Wayland_Vulkan_LoadLibrary(_THIS, const char *path);
|
||||
void Wayland_Vulkan_UnloadLibrary(_THIS);
|
||||
SDL_bool Wayland_Vulkan_GetInstanceExtensions(_THIS,
|
||||
SDL_Window *window,
|
||||
unsigned *count,
|
||||
const char **names);
|
||||
SDL_bool Wayland_Vulkan_CreateSurface(_THIS,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _SDL_waylandvulkan_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
@@ -33,6 +33,7 @@
|
||||
#include "SDL_windowsvideo.h"
|
||||
#include "SDL_windowsframebuffer.h"
|
||||
#include "SDL_windowsshape.h"
|
||||
#include "SDL_windowsvulkan.h"
|
||||
|
||||
/* Initialization/Query functions */
|
||||
static int WIN_VideoInit(_THIS);
|
||||
@@ -190,6 +191,13 @@ WIN_CreateDevice(int devindex)
|
||||
device->GL_SwapWindow = WIN_GLES_SwapWindow;
|
||||
device->GL_DeleteContext = WIN_GLES_DeleteContext;
|
||||
#endif
|
||||
#if SDL_VIDEO_VULKAN_SURFACE
|
||||
device->Vulkan_LoadLibrary = WIN_Vulkan_LoadLibrary;
|
||||
device->Vulkan_UnloadLibrary = WIN_Vulkan_UnloadLibrary;
|
||||
device->Vulkan_GetInstanceExtensions = WIN_Vulkan_GetInstanceExtensions;
|
||||
device->Vulkan_CreateSurface = WIN_Vulkan_CreateSurface;
|
||||
#endif
|
||||
|
||||
device->StartTextInput = WIN_StartTextInput;
|
||||
device->StopTextInput = WIN_StopTextInput;
|
||||
device->SetTextInputRect = WIN_SetTextInputRect;
|
||||
|
176
src/video/windows/SDL_windowsvulkan.c
Normal file
176
src/video/windows/SDL_windowsvulkan.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
|
||||
* SDL_x11vulkan.c.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE && SDL_VIDEO_DRIVER_WINDOWS
|
||||
|
||||
#include "SDL_windowsvideo.h"
|
||||
#include "SDL_windowswindow.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
#include "SDL_windowsvulkan.h"
|
||||
#include "SDL_syswm.h"
|
||||
|
||||
int WIN_Vulkan_LoadLibrary(_THIS, const char *path)
|
||||
{
|
||||
VkExtensionProperties *extensions = NULL;
|
||||
Uint32 extensionCount = 0;
|
||||
Uint32 i;
|
||||
SDL_bool hasSurfaceExtension = SDL_FALSE;
|
||||
SDL_bool hasWin32SurfaceExtension = SDL_FALSE;
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
|
||||
if(_this->vulkan_config.loader_handle)
|
||||
return SDL_SetError("Vulkan already loaded");
|
||||
|
||||
/* Load the Vulkan loader library */
|
||||
if(!path)
|
||||
path = SDL_getenv("SDL_VULKAN_LIBRARY");
|
||||
if(!path)
|
||||
path = "vulkan-1.dll";
|
||||
_this->vulkan_config.loader_handle = SDL_LoadObject(path);
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
return -1;
|
||||
SDL_strlcpy(_this->vulkan_config.loader_path, path,
|
||||
SDL_arraysize(_this->vulkan_config.loader_path));
|
||||
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
|
||||
_this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
|
||||
if(!vkGetInstanceProcAddr)
|
||||
goto fail;
|
||||
_this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties =
|
||||
(void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)(
|
||||
VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
|
||||
if(!_this->vulkan_config.vkEnumerateInstanceExtensionProperties)
|
||||
goto fail;
|
||||
extensions = SDL_Vulkan_CreateInstanceExtensionsList(
|
||||
(PFN_vkEnumerateInstanceExtensionProperties)
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties,
|
||||
&extensionCount);
|
||||
if(!extensions)
|
||||
goto fail;
|
||||
for(i = 0; i < extensionCount; i++)
|
||||
{
|
||||
if(SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
|
||||
hasSurfaceExtension = SDL_TRUE;
|
||||
else if(SDL_strcmp(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
|
||||
hasWin32SurfaceExtension = SDL_TRUE;
|
||||
}
|
||||
SDL_free(extensions);
|
||||
if(!hasSurfaceExtension)
|
||||
{
|
||||
SDL_SetError("Installed Vulkan doesn't implement the "
|
||||
VK_KHR_SURFACE_EXTENSION_NAME " extension");
|
||||
goto fail;
|
||||
}
|
||||
else if(!hasWin32SurfaceExtension)
|
||||
{
|
||||
SDL_SetError("Installed Vulkan doesn't implement the "
|
||||
VK_KHR_WIN32_SURFACE_EXTENSION_NAME "extension");
|
||||
goto fail;
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void WIN_Vulkan_UnloadLibrary(_THIS)
|
||||
{
|
||||
if(_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool WIN_Vulkan_GetInstanceExtensions(_THIS,
|
||||
SDL_Window *window,
|
||||
unsigned *count,
|
||||
const char **names)
|
||||
{
|
||||
static const char *const extensionsForWin32[] = {
|
||||
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME
|
||||
};
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_Vulkan_GetInstanceExtensions_Helper(
|
||||
count, names, SDL_arraysize(extensionsForWin32),
|
||||
extensionsForWin32);
|
||||
}
|
||||
|
||||
SDL_bool WIN_Vulkan_CreateSurface(_THIS,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface)
|
||||
{
|
||||
SDL_WindowData *windowData = (SDL_WindowData *)window->driverdata;
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
|
||||
(PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
|
||||
PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR =
|
||||
(PFN_vkCreateWin32SurfaceKHR)vkGetInstanceProcAddr(
|
||||
(VkInstance)instance,
|
||||
"vkCreateWin32SurfaceKHR");
|
||||
VkWin32SurfaceCreateInfoKHR createInfo;
|
||||
VkResult result;
|
||||
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if(!vkCreateWin32SurfaceKHR)
|
||||
{
|
||||
SDL_SetError(VK_KHR_WIN32_SURFACE_EXTENSION_NAME
|
||||
" extension is not enabled in the Vulkan instance.");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
||||
createInfo.pNext = NULL;
|
||||
createInfo.flags = 0;
|
||||
createInfo.hinstance = windowData->hinstance;
|
||||
createInfo.hwnd = windowData->hwnd;
|
||||
result = vkCreateWin32SurfaceKHR(instance, &createInfo,
|
||||
NULL, surface);
|
||||
if(result != VK_SUCCESS)
|
||||
{
|
||||
SDL_SetError("vkCreateWin32SurfaceKHR failed: %s",
|
||||
SDL_Vulkan_GetResultString(result));
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
52
src/video/windows/SDL_windowsvulkan.h
Normal file
52
src/video/windows/SDL_windowsvulkan.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
|
||||
* SDL_x11vulkan.h.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef _SDL_windowsvulkan_h
|
||||
#define _SDL_windowsvulkan_h
|
||||
|
||||
#include "../SDL_vulkan_internal.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE && SDL_VIDEO_DRIVER_WINDOWS
|
||||
|
||||
int WIN_Vulkan_LoadLibrary(_THIS, const char *path);
|
||||
void WIN_Vulkan_UnloadLibrary(_THIS);
|
||||
SDL_bool WIN_Vulkan_GetInstanceExtensions(_THIS,
|
||||
SDL_Window *window,
|
||||
unsigned *count,
|
||||
const char **names);
|
||||
SDL_bool WIN_Vulkan_CreateSurface(_THIS,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _SDL_windowsvulkan_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
@@ -40,6 +40,8 @@
|
||||
#include "SDL_x11opengles.h"
|
||||
#endif
|
||||
|
||||
#include "SDL_x11vulkan.h"
|
||||
|
||||
/* Initialization/Query functions */
|
||||
static int X11_VideoInit(_THIS);
|
||||
static void X11_VideoQuit(_THIS);
|
||||
@@ -107,6 +109,9 @@ static void
|
||||
X11_DeleteDevice(SDL_VideoDevice * device)
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *) device->driverdata;
|
||||
if (device->vulkan_config.loader_handle) {
|
||||
device->Vulkan_UnloadLibrary(device);
|
||||
}
|
||||
if (data->display) {
|
||||
X11_XCloseDisplay(data->display);
|
||||
}
|
||||
@@ -291,6 +296,13 @@ X11_CreateDevice(int devindex)
|
||||
|
||||
device->free = X11_DeleteDevice;
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE
|
||||
device->Vulkan_LoadLibrary = X11_Vulkan_LoadLibrary;
|
||||
device->Vulkan_UnloadLibrary = X11_Vulkan_UnloadLibrary;
|
||||
device->Vulkan_GetInstanceExtensions = X11_Vulkan_GetInstanceExtensions;
|
||||
device->Vulkan_CreateSurface = X11_Vulkan_CreateSurface;
|
||||
#endif
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
|
@@ -68,6 +68,7 @@
|
||||
#include "SDL_x11mouse.h"
|
||||
#include "SDL_x11opengl.h"
|
||||
#include "SDL_x11window.h"
|
||||
#include "SDL_x11vulkan.h"
|
||||
|
||||
/* Private display data */
|
||||
|
||||
@@ -140,6 +141,12 @@ typedef struct SDL_VideoData
|
||||
KeyCode filter_code;
|
||||
Time filter_time;
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE
|
||||
/* Vulkan variables only valid if _this->vulkan_config.loader_handle is not NULL */
|
||||
void *vulkan_xlib_xcb_library;
|
||||
PFN_XGetXCBConnection vulkan_XGetXCBConnection;
|
||||
#endif
|
||||
|
||||
} SDL_VideoData;
|
||||
|
||||
extern SDL_bool X11_UseDirectColorVisuals(void);
|
||||
|
239
src/video/x11/SDL_x11vulkan.c
Normal file
239
src/video/x11/SDL_x11vulkan.c
Normal file
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 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.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE && SDL_VIDEO_DRIVER_X11
|
||||
|
||||
#include "SDL_x11video.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
#include "SDL_x11vulkan.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
//#include <xcb/xcb.h>
|
||||
typedef uint32_t xcb_window_t;
|
||||
typedef uint32_t xcb_visualid_t;
|
||||
|
||||
int X11_Vulkan_LoadLibrary(_THIS, const char *path)
|
||||
{
|
||||
SDL_VideoData *videoData = (SDL_VideoData *)_this->driverdata;
|
||||
VkExtensionProperties *extensions = NULL;
|
||||
Uint32 extensionCount = 0;
|
||||
SDL_bool hasSurfaceExtension = SDL_FALSE;
|
||||
SDL_bool hasXlibSurfaceExtension = SDL_FALSE;
|
||||
SDL_bool hasXCBSurfaceExtension = SDL_FALSE;
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
|
||||
Uint32 i;
|
||||
if(_this->vulkan_config.loader_handle)
|
||||
return SDL_SetError("Vulkan already loaded");
|
||||
|
||||
/* Load the Vulkan loader library */
|
||||
if(!path)
|
||||
path = SDL_getenv("SDL_VULKAN_LIBRARY");
|
||||
if(!path)
|
||||
path = "libvulkan.so.1";
|
||||
_this->vulkan_config.loader_handle = SDL_LoadObject(path);
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
return -1;
|
||||
SDL_strlcpy(_this->vulkan_config.loader_path, path, SDL_arraysize(_this->vulkan_config.loader_path));
|
||||
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
|
||||
_this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
|
||||
if(!vkGetInstanceProcAddr)
|
||||
goto fail;
|
||||
_this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties =
|
||||
(void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)(
|
||||
VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
|
||||
if(!_this->vulkan_config.vkEnumerateInstanceExtensionProperties)
|
||||
goto fail;
|
||||
extensions = SDL_Vulkan_CreateInstanceExtensionsList(
|
||||
(PFN_vkEnumerateInstanceExtensionProperties)
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties,
|
||||
&extensionCount);
|
||||
if(!extensions)
|
||||
goto fail;
|
||||
for(i = 0; i < extensionCount; i++)
|
||||
{
|
||||
if(SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
|
||||
hasSurfaceExtension = SDL_TRUE;
|
||||
else if(SDL_strcmp(VK_KHR_XCB_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
|
||||
hasXCBSurfaceExtension = SDL_TRUE;
|
||||
else if(SDL_strcmp(VK_KHR_XLIB_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
|
||||
hasXlibSurfaceExtension = SDL_TRUE;
|
||||
}
|
||||
SDL_free(extensions);
|
||||
if(!hasSurfaceExtension)
|
||||
{
|
||||
SDL_SetError("Installed Vulkan doesn't implement the "
|
||||
VK_KHR_SURFACE_EXTENSION_NAME " extension");
|
||||
goto fail;
|
||||
}
|
||||
if(hasXlibSurfaceExtension)
|
||||
{
|
||||
videoData->vulkan_xlib_xcb_library = NULL;
|
||||
}
|
||||
else if(!hasXCBSurfaceExtension)
|
||||
{
|
||||
SDL_SetError("Installed Vulkan doesn't implement either the "
|
||||
VK_KHR_XCB_SURFACE_EXTENSION_NAME "extension or the "
|
||||
VK_KHR_XLIB_SURFACE_EXTENSION_NAME " extension");
|
||||
goto fail;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *libX11XCBLibraryName = SDL_getenv("SDL_X11_XCB_LIBRARY");
|
||||
if(!libX11XCBLibraryName)
|
||||
libX11XCBLibraryName = "libX11-xcb.so";
|
||||
videoData->vulkan_xlib_xcb_library = SDL_LoadObject(libX11XCBLibraryName);
|
||||
if(!videoData->vulkan_xlib_xcb_library)
|
||||
goto fail;
|
||||
videoData->vulkan_XGetXCBConnection =
|
||||
SDL_LoadFunction(videoData->vulkan_xlib_xcb_library, "XGetXCBConnection");
|
||||
if(!videoData->vulkan_XGetXCBConnection)
|
||||
{
|
||||
SDL_UnloadObject(videoData->vulkan_xlib_xcb_library);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void X11_Vulkan_UnloadLibrary(_THIS)
|
||||
{
|
||||
SDL_VideoData *videoData = (SDL_VideoData *)_this->driverdata;
|
||||
if(_this->vulkan_config.loader_handle)
|
||||
{
|
||||
if(videoData->vulkan_xlib_xcb_library)
|
||||
SDL_UnloadObject(videoData->vulkan_xlib_xcb_library);
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool X11_Vulkan_GetInstanceExtensions(_THIS,
|
||||
SDL_Window *window,
|
||||
unsigned *count,
|
||||
const char **names)
|
||||
{
|
||||
SDL_VideoData *videoData = (SDL_VideoData *)_this->driverdata;
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
if(videoData->vulkan_xlib_xcb_library)
|
||||
{
|
||||
static const char *const extensionsForXCB[] = {
|
||||
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME,
|
||||
};
|
||||
return SDL_Vulkan_GetInstanceExtensions_Helper(
|
||||
count, names, SDL_arraysize(extensionsForXCB), extensionsForXCB);
|
||||
}
|
||||
else
|
||||
{
|
||||
static const char *const extensionsForXlib[] = {
|
||||
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
|
||||
};
|
||||
return SDL_Vulkan_GetInstanceExtensions_Helper(
|
||||
count, names, SDL_arraysize(extensionsForXlib), extensionsForXlib);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool X11_Vulkan_CreateSurface(_THIS,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface)
|
||||
{
|
||||
SDL_VideoData *videoData = (SDL_VideoData *)_this->driverdata;
|
||||
SDL_WindowData *windowData = (SDL_WindowData *)window->driverdata;
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
|
||||
if(!_this->vulkan_config.loader_handle)
|
||||
{
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
|
||||
if(videoData->vulkan_xlib_xcb_library)
|
||||
{
|
||||
PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR =
|
||||
(PFN_vkCreateXcbSurfaceKHR)vkGetInstanceProcAddr((VkInstance)instance,
|
||||
"vkCreateXcbSurfaceKHR");
|
||||
VkXcbSurfaceCreateInfoKHR createInfo = {};
|
||||
VkResult result;
|
||||
if(!vkCreateXcbSurfaceKHR)
|
||||
{
|
||||
SDL_SetError(VK_KHR_XCB_SURFACE_EXTENSION_NAME
|
||||
" extension is not enabled in the Vulkan instance.");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
|
||||
createInfo.connection = videoData->vulkan_XGetXCBConnection(videoData->display);
|
||||
if(!createInfo.connection)
|
||||
{
|
||||
SDL_SetError("XGetXCBConnection failed");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
createInfo.window = (xcb_window_t)windowData->xwindow;
|
||||
result = vkCreateXcbSurfaceKHR(instance, &createInfo,
|
||||
NULL, surface);
|
||||
if(result != VK_SUCCESS)
|
||||
{
|
||||
SDL_SetError("vkCreateXcbSurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result));
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR =
|
||||
(PFN_vkCreateXlibSurfaceKHR)vkGetInstanceProcAddr((VkInstance)instance,
|
||||
"vkCreateXlibSurfaceKHR");
|
||||
VkXlibSurfaceCreateInfoKHR createInfo = {};
|
||||
VkResult result;
|
||||
if(!vkCreateXlibSurfaceKHR)
|
||||
{
|
||||
SDL_SetError(VK_KHR_XLIB_SURFACE_EXTENSION_NAME
|
||||
" extension is not enabled in the Vulkan instance.");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
|
||||
createInfo.dpy = videoData->display;
|
||||
createInfo.window = (xcb_window_t)windowData->xwindow;
|
||||
result = vkCreateXlibSurfaceKHR(instance, &createInfo,
|
||||
NULL, surface);
|
||||
if(result != VK_SUCCESS)
|
||||
{
|
||||
SDL_SetError("vkCreateXlibSurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result));
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* vim: set ts=4 sw=4 expandtab: */
|
48
src/video/x11/SDL_x11vulkan.h
Normal file
48
src/video/x11/SDL_x11vulkan.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 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.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef _SDL_x11vulkan_h
|
||||
#define _SDL_x11vulkan_h
|
||||
|
||||
#include "../SDL_vulkan_internal.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN_SURFACE && SDL_VIDEO_DRIVER_X11
|
||||
|
||||
typedef struct xcb_connection_t xcb_connection_t;
|
||||
typedef xcb_connection_t *(*PFN_XGetXCBConnection)(Display *dpy);
|
||||
|
||||
int X11_Vulkan_LoadLibrary(_THIS, const char *path);
|
||||
void X11_Vulkan_UnloadLibrary(_THIS);
|
||||
SDL_bool X11_Vulkan_GetInstanceExtensions(_THIS,
|
||||
SDL_Window *window,
|
||||
unsigned *count,
|
||||
const char **names);
|
||||
SDL_bool X11_Vulkan_CreateSurface(_THIS,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _SDL_x11vulkan_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
Reference in New Issue
Block a user