2017-08-27 21:15:57 -05:00
/*
Simple DirectMedia Layer
2023-01-09 11:41:41 -06:00
Copyright ( C ) 1997 - 2023 Sam Lantinga < slouken @ libsdl . org >
2017-08-27 21:15:57 -05:00
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 .
*/
2022-11-29 20:34:15 -06:00
# include "SDL_internal.h"
2017-08-27 21:15:57 -05:00
2017-08-28 02:11:38 -05:00
# if SDL_VIDEO_VULKAN && SDL_VIDEO_DRIVER_X11
2017-08-27 21:15:57 -05:00
# include "SDL_x11video.h"
# include "SDL_x11vulkan.h"
# include <X11/Xlib.h>
2017-08-28 02:51:14 -05:00
/*#include <xcb/xcb.h>*/
2020-09-08 10:42:30 -05:00
# if defined(__OpenBSD__)
2022-11-30 14:51:59 -06:00
# define DEFAULT_VULKAN "libvulkan.so"
2020-09-08 10:42:30 -05:00
# else
2022-11-30 14:51:59 -06:00
# define DEFAULT_VULKAN "libvulkan.so.1"
2020-09-08 10:42:30 -05:00
# endif
2017-08-28 02:51:14 -05:00
/*
2017-08-27 21:15:57 -05:00
typedef uint32_t xcb_window_t ;
typedef uint32_t xcb_visualid_t ;
2017-08-28 02:51:14 -05:00
*/
2017-08-27 21:15:57 -05:00
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 ;
2022-11-27 10:38:43 -06:00
if ( _this - > vulkan_config . loader_handle ) {
2017-08-27 21:15:57 -05:00
return SDL_SetError ( " Vulkan already loaded " ) ;
2022-11-27 10:38:43 -06:00
}
2017-08-27 21:15:57 -05:00
/* Load the Vulkan loader library */
2022-11-27 10:38:43 -06:00
if ( path = = NULL ) {
2017-08-27 21:15:57 -05:00
path = SDL_getenv ( " SDL_VULKAN_LIBRARY " ) ;
2022-11-27 10:38:43 -06:00
}
if ( path = = NULL ) {
2020-09-08 10:42:30 -05:00
path = DEFAULT_VULKAN ;
2022-11-27 10:38:43 -06:00
}
2017-08-27 21:15:57 -05:00
_this - > vulkan_config . loader_handle = SDL_LoadObject ( path ) ;
2022-11-27 10:38:43 -06:00
if ( ! _this - > vulkan_config . loader_handle ) {
2017-08-27 21:15:57 -05:00
return - 1 ;
2022-11-27 10:38:43 -06:00
}
2017-08-27 21:15:57 -05:00
SDL_strlcpy ( _this - > vulkan_config . loader_path , path , SDL_arraysize ( _this - > vulkan_config . loader_path ) ) ;
2018-02-12 08:00:00 -06:00
vkGetInstanceProcAddr = ( PFN_vkGetInstanceProcAddr ) SDL_LoadFunction (
2017-08-27 21:15:57 -05:00
_this - > vulkan_config . loader_handle , " vkGetInstanceProcAddr " ) ;
2022-11-27 10:38:43 -06:00
if ( ! vkGetInstanceProcAddr ) {
2017-08-27 21:15:57 -05:00
goto fail ;
2022-11-27 10:38:43 -06:00
}
2018-02-12 08:00:00 -06:00
_this - > vulkan_config . vkGetInstanceProcAddr = ( void * ) vkGetInstanceProcAddr ;
2017-08-27 21:15:57 -05:00
_this - > vulkan_config . vkEnumerateInstanceExtensionProperties =
2018-02-12 08:00:00 -06:00
( void * ) ( ( PFN_vkGetInstanceProcAddr ) _this - > vulkan_config . vkGetInstanceProcAddr ) (
VK_NULL_HANDLE , " vkEnumerateInstanceExtensionProperties " ) ;
2022-11-27 10:38:43 -06:00
if ( ! _this - > vulkan_config . vkEnumerateInstanceExtensionProperties ) {
2017-08-27 21:15:57 -05:00
goto fail ;
2022-11-27 10:38:43 -06:00
}
2017-08-27 21:15:57 -05:00
extensions = SDL_Vulkan_CreateInstanceExtensionsList (
( PFN_vkEnumerateInstanceExtensionProperties )
_this - > vulkan_config . vkEnumerateInstanceExtensionProperties ,
& extensionCount ) ;
2022-11-27 10:38:43 -06:00
if ( extensions = = NULL ) {
2017-08-27 21:15:57 -05:00
goto fail ;
2022-11-27 10:38:43 -06:00
}
2022-11-30 14:51:59 -06:00
for ( i = 0 ; i < extensionCount ; i + + ) {
2022-11-27 10:38:43 -06:00
if ( SDL_strcmp ( VK_KHR_SURFACE_EXTENSION_NAME , extensions [ i ] . extensionName ) = = 0 ) {
2017-08-27 21:15:57 -05:00
hasSurfaceExtension = SDL_TRUE ;
2022-11-27 10:38:43 -06:00
} else if ( SDL_strcmp ( VK_KHR_XCB_SURFACE_EXTENSION_NAME , extensions [ i ] . extensionName ) = = 0 ) {
2017-08-27 21:15:57 -05:00
hasXCBSurfaceExtension = SDL_TRUE ;
2022-11-27 10:38:43 -06:00
} else if ( SDL_strcmp ( VK_KHR_XLIB_SURFACE_EXTENSION_NAME , extensions [ i ] . extensionName ) = = 0 ) {
2017-08-27 21:15:57 -05:00
hasXlibSurfaceExtension = SDL_TRUE ;
2022-11-27 10:38:43 -06:00
}
2017-08-27 21:15:57 -05:00
}
SDL_free ( extensions ) ;
2022-11-27 10:38:43 -06:00
if ( ! hasSurfaceExtension ) {
2022-11-30 14:51:59 -06:00
SDL_SetError ( " Installed Vulkan doesn't implement the " VK_KHR_SURFACE_EXTENSION_NAME " extension " ) ;
2017-08-27 21:15:57 -05:00
goto fail ;
}
2022-11-27 10:38:43 -06:00
if ( hasXlibSurfaceExtension ) {
2017-08-27 21:15:57 -05:00
videoData - > vulkan_xlib_xcb_library = NULL ;
2022-11-27 10:38:43 -06:00
} else if ( ! hasXCBSurfaceExtension ) {
2022-11-30 14:51:59 -06:00
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 " ) ;
2017-08-27 21:15:57 -05:00
goto fail ;
2022-11-27 10:38:43 -06:00
} else {
2017-08-27 21:15:57 -05:00
const char * libX11XCBLibraryName = SDL_getenv ( " SDL_X11_XCB_LIBRARY " ) ;
2022-11-27 10:38:43 -06:00
if ( libX11XCBLibraryName = = NULL ) {
2017-08-27 21:15:57 -05:00
libX11XCBLibraryName = " libX11-xcb.so " ;
2022-11-27 10:38:43 -06:00
}
2017-08-27 21:15:57 -05:00
videoData - > vulkan_xlib_xcb_library = SDL_LoadObject ( libX11XCBLibraryName ) ;
2022-11-27 10:38:43 -06:00
if ( ! videoData - > vulkan_xlib_xcb_library ) {
2017-08-27 21:15:57 -05:00
goto fail ;
2022-11-27 10:38:43 -06:00
}
2018-02-12 08:00:00 -06:00
videoData - > vulkan_XGetXCBConnection =
2023-01-09 16:55:12 -06:00
( PFN_XGetXCBConnection ) SDL_LoadFunction ( videoData - > vulkan_xlib_xcb_library , " XGetXCBConnection " ) ;
2022-11-27 10:38:43 -06:00
if ( ! videoData - > vulkan_XGetXCBConnection ) {
2017-08-27 21:15:57 -05:00
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 ;
2022-11-27 10:38:43 -06:00
if ( _this - > vulkan_config . loader_handle ) {
if ( videoData - > vulkan_xlib_xcb_library ) {
2017-08-27 21:15:57 -05:00
SDL_UnloadObject ( videoData - > vulkan_xlib_xcb_library ) ;
2022-11-27 10:38:43 -06:00
}
2017-08-27 21:15:57 -05:00
SDL_UnloadObject ( _this - > vulkan_config . loader_handle ) ;
_this - > vulkan_config . loader_handle = NULL ;
}
}
SDL_bool X11_Vulkan_GetInstanceExtensions ( _THIS ,
unsigned * count ,
const char * * names )
{
SDL_VideoData * videoData = ( SDL_VideoData * ) _this - > driverdata ;
2022-11-27 10:38:43 -06:00
if ( ! _this - > vulkan_config . loader_handle ) {
2017-08-27 21:15:57 -05:00
SDL_SetError ( " Vulkan is not loaded " ) ;
return SDL_FALSE ;
}
2022-11-27 10:38:43 -06:00
if ( videoData - > vulkan_xlib_xcb_library ) {
2017-08-27 21:15:57 -05:00
static const char * const extensionsForXCB [ ] = {
2022-11-30 14:51:59 -06:00
VK_KHR_SURFACE_EXTENSION_NAME ,
VK_KHR_XCB_SURFACE_EXTENSION_NAME ,
2017-08-27 21:15:57 -05:00
} ;
return SDL_Vulkan_GetInstanceExtensions_Helper (
count , names , SDL_arraysize ( extensionsForXCB ) , extensionsForXCB ) ;
2022-11-27 10:38:43 -06:00
} else {
2017-08-27 21:15:57 -05:00
static const char * const extensionsForXlib [ ] = {
2022-11-30 14:51:59 -06:00
VK_KHR_SURFACE_EXTENSION_NAME ,
VK_KHR_XLIB_SURFACE_EXTENSION_NAME ,
2017-08-27 21:15:57 -05:00
} ;
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 ;
2022-11-27 10:38:43 -06:00
if ( ! _this - > vulkan_config . loader_handle ) {
2017-08-27 21:15:57 -05:00
SDL_SetError ( " Vulkan is not loaded " ) ;
return SDL_FALSE ;
}
vkGetInstanceProcAddr = ( PFN_vkGetInstanceProcAddr ) _this - > vulkan_config . vkGetInstanceProcAddr ;
2022-11-27 10:38:43 -06:00
if ( videoData - > vulkan_xlib_xcb_library ) {
2017-08-27 21:15:57 -05:00
PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR =
2019-10-30 09:13:55 -05:00
( PFN_vkCreateXcbSurfaceKHR ) vkGetInstanceProcAddr ( instance ,
2017-08-27 21:15:57 -05:00
" vkCreateXcbSurfaceKHR " ) ;
2018-01-30 20:08:34 -06:00
VkXcbSurfaceCreateInfoKHR createInfo ;
2017-08-27 21:15:57 -05:00
VkResult result ;
2022-11-27 10:38:43 -06:00
if ( ! vkCreateXcbSurfaceKHR ) {
2017-08-27 21:15:57 -05:00
SDL_SetError ( VK_KHR_XCB_SURFACE_EXTENSION_NAME
" extension is not enabled in the Vulkan instance. " ) ;
return SDL_FALSE ;
}
2018-01-30 20:08:34 -06:00
SDL_zero ( createInfo ) ;
2017-08-27 21:15:57 -05:00
createInfo . sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR ;
createInfo . connection = videoData - > vulkan_XGetXCBConnection ( videoData - > display ) ;
2022-11-27 10:38:43 -06:00
if ( ! createInfo . connection ) {
2017-08-27 21:15:57 -05:00
SDL_SetError ( " XGetXCBConnection failed " ) ;
return SDL_FALSE ;
}
createInfo . window = ( xcb_window_t ) windowData - > xwindow ;
result = vkCreateXcbSurfaceKHR ( instance , & createInfo ,
NULL , surface ) ;
2022-11-27 10:38:43 -06:00
if ( result ! = VK_SUCCESS ) {
2017-08-27 21:15:57 -05:00
SDL_SetError ( " vkCreateXcbSurfaceKHR failed: %s " , SDL_Vulkan_GetResultString ( result ) ) ;
return SDL_FALSE ;
}
return SDL_TRUE ;
2022-11-27 10:38:43 -06:00
} else {
2017-08-27 21:15:57 -05:00
PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR =
2019-10-30 09:13:55 -05:00
( PFN_vkCreateXlibSurfaceKHR ) vkGetInstanceProcAddr ( instance ,
2017-08-27 21:15:57 -05:00
" vkCreateXlibSurfaceKHR " ) ;
2018-01-30 20:08:34 -06:00
VkXlibSurfaceCreateInfoKHR createInfo ;
2017-08-27 21:15:57 -05:00
VkResult result ;
2022-11-27 10:38:43 -06:00
if ( ! vkCreateXlibSurfaceKHR ) {
2017-08-27 21:15:57 -05:00
SDL_SetError ( VK_KHR_XLIB_SURFACE_EXTENSION_NAME
" extension is not enabled in the Vulkan instance. " ) ;
return SDL_FALSE ;
}
2018-01-30 20:08:34 -06:00
SDL_zero ( createInfo ) ;
2017-08-27 21:15:57 -05:00
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 ) ;
2022-11-27 10:38:43 -06:00
if ( result ! = VK_SUCCESS ) {
2017-08-27 21:15:57 -05:00
SDL_SetError ( " vkCreateXlibSurfaceKHR failed: %s " , SDL_Vulkan_GetResultString ( result ) ) ;
return SDL_FALSE ;
}
return SDL_TRUE ;
}
}
# endif
/* vim: set ts=4 sw=4 expandtab: */