From f0a1dc2f20348f7b54ce4b5a2e9979f9d8181d69 Mon Sep 17 00:00:00 2001 From: redstrate <54911369+redstrate@users.noreply.github.com> Date: Mon, 1 Mar 2021 14:40:02 -0500 Subject: [PATCH] Add experimental SDL backend for Linux --- engine/gfx/vulkan/src/gfx_vulkan.cpp | 28 ++- engine/platform/include/platform.hpp | 4 + platforms/CMakeLists.txt | 10 +- platforms/sdl/CMakeLists.txt | 21 +++ platforms/sdl/file.cpp | 11 ++ platforms/sdl/main.cpp.in | 243 +++++++++++++++++++++++++++ 6 files changed, 295 insertions(+), 22 deletions(-) create mode 100644 platforms/sdl/CMakeLists.txt create mode 100644 platforms/sdl/file.cpp create mode 100644 platforms/sdl/main.cpp.in diff --git a/engine/gfx/vulkan/src/gfx_vulkan.cpp b/engine/gfx/vulkan/src/gfx_vulkan.cpp index 546d41c..86a6ed9 100755 --- a/engine/gfx/vulkan/src/gfx_vulkan.cpp +++ b/engine/gfx/vulkan/src/gfx_vulkan.cpp @@ -18,6 +18,12 @@ #include "utility.hpp" #include "gfx_vulkan_commandbuffer.hpp" +#ifdef PLATFORM_LINUX +#include +#include + +#endif + VkFormat toVkFormat(GFXPixelFormat format) { switch (format) { case GFXPixelFormat::R_32F: @@ -180,8 +186,6 @@ VkResult name_object(VkDevice device, VkObjectType type, uint64_t object, std::s bool GFXVulkan::initialize(const GFXCreateInfo& info) { #ifdef PLATFORM_WINDOWS const char* surface_name = "VK_KHR_win32_surface"; -#else - const char* surface_name = VK_KHR_XCB_SURFACE_EXTENSION_NAME; #endif uint32_t extensionPropertyCount = 0; @@ -190,12 +194,15 @@ bool GFXVulkan::initialize(const GFXCreateInfo& info) { std::vector extensionProperties(extensionPropertyCount); vkEnumerateInstanceExtensionProperties(nullptr, &extensionPropertyCount, extensionProperties.data()); - std::vector enabledExtensions = { "VK_KHR_surface", surface_name }; + std::vector enabledExtensions = {}; for (auto prop : extensionProperties) { if (!strcmp(prop.extensionName, "VK_EXT_debug_utils")) enabledExtensions.push_back("VK_EXT_debug_utils"); } + auto required_extensions = platform::get_native_surface_extension(); + enabledExtensions.insert(enabledExtensions.end(), required_extensions.begin(), required_extensions.end()); + createInstance({}, enabledExtensions); createLogicalDevice({ VK_KHR_SWAPCHAIN_EXTENSION_NAME }); createDescriptorPool(); @@ -1450,20 +1457,7 @@ void GFXVulkan::createSwapchain(NativeSurface* native_surface, VkSwapchainKHR ol } #else if(native_surface->surface == VK_NULL_HANDLE) { - struct WindowConnection { - int identifier = 0; - xcb_connection_t* connection; - xcb_window_t window; - }; - - WindowConnection* wincon = reinterpret_cast(native_surface->windowNativeHandle); - - VkXcbSurfaceCreateInfoKHR createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; - createInfo.window = wincon->window; - createInfo.connection = wincon->connection; - - vkCreateXcbSurfaceKHR(instance, &createInfo, nullptr, &native_surface->surface); + native_surface->surface = (VkSurfaceKHR)platform::create_native_surface(native_surface->identifier, (void*)instance); } #endif diff --git a/engine/platform/include/platform.hpp b/engine/platform/include/platform.hpp index 9464c42..9bb0eaa 100755 --- a/engine/platform/include/platform.hpp +++ b/engine/platform/include/platform.hpp @@ -84,6 +84,10 @@ namespace platform { */ int open_window(const std::string_view title, const prism::Rectangle rect, const WindowFlags flags); + // for vulkan usage + void* create_native_surface(int index, void* instance); + std::vector get_native_surface_extension(); + /** Closes a window. @param index The window to close. */ diff --git a/platforms/CMakeLists.txt b/platforms/CMakeLists.txt index 8b213be..5849c9b 100755 --- a/platforms/CMakeLists.txt +++ b/platforms/CMakeLists.txt @@ -3,17 +3,17 @@ if(ENABLE_WINDOWS) endif() if(ENABLE_LINUX) - add_subdirectory(linux) + add_subdirectory(sdl) endif() if(ENABLE_MACOS) add_subdirectory(mac) -endif() - +endif() + if(ENABLE_IOS) add_subdirectory(ios) -endif() - +endif() + if(ENABLE_TVOS) add_subdirectory(tvos) endif() \ No newline at end of file diff --git a/platforms/sdl/CMakeLists.txt b/platforms/sdl/CMakeLists.txt new file mode 100644 index 0000000..454cf7b --- /dev/null +++ b/platforms/sdl/CMakeLists.txt @@ -0,0 +1,21 @@ +include(../../cmake/AddPlatformExecutable.cmake) + +add_platform( + SRC ${CMAKE_CURRENT_SOURCE_DIR}/file.cpp + MAIN_FILE + main.cpp.in + LINK_LIBRARIES + SDL2 + Core + GFXVulkan +) + +function(add_platform_commands target) + if(NOT SKIP_DATA) + add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/data $/data) + endif() + + add_custom_command(TARGET ${target} PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory $/shaders) + + add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/shaders $/shaders) +endfunction() diff --git a/platforms/sdl/file.cpp b/platforms/sdl/file.cpp new file mode 100644 index 0000000..0221fa6 --- /dev/null +++ b/platforms/sdl/file.cpp @@ -0,0 +1,11 @@ +#include "file.hpp" + +#include "string_utils.hpp" + +void file::set_domain_path(const file::Domain domain, const file::Path path) { + domain_data[(int)domain] = replace_substring(path.string(), "{resource_dir}/", ""); +} + +file::Path file::get_writeable_directory() { + return "~"; +} diff --git a/platforms/sdl/main.cpp.in b/platforms/sdl/main.cpp.in new file mode 100644 index 0000000..dc2a595 --- /dev/null +++ b/platforms/sdl/main.cpp.in @@ -0,0 +1,243 @@ +#include <@APP_INCLUDE@> +#include + +#include "gfx_vulkan.hpp" +#include "platform.hpp" + +#include +#include + +@APP_CLASS@* app = nullptr; +GFX* interface = nullptr; + +struct Window { + int identifier = 0; + SDL_Window* window = nullptr; +}; + +std::vector windows; + +static std::map inputToKeyCode = { { + {InputButton::A, 38}, + {InputButton::W, 25}, + {InputButton::S, 39}, + {InputButton::D, 40}, + {InputButton::Q, 24} +}}; + +/* + * Platform functions" + */ + +const char* platform::get_name() { + return "Linux (SDL)"; +} + +bool platform::supports_feature(const PlatformFeature feature) { + if(feature == PlatformFeature::Windowing) + return true; + + return false; +} + +int platform::open_window(const std::string_view title, const prism::Rectangle rect, const WindowFlags flags) { + auto& win = windows.emplace_back(); + win.identifier = windows.size() - 1; + + win.window = SDL_CreateWindow(title.data(), rect.offset.x, rect.offset.y, rect.extent.width, rect.extent.height, SDL_WINDOW_VULKAN); + + engine->add_window((void*)&win, 0, rect.extent); + app->initialize_render(); + + return win.identifier; +} + +void platform::close_window(const int index) { +} + +void platform::force_quit() { +} + +float platform::get_window_dpi(const int index) { + return 1.0; +} + +float platform::get_monitor_dpi() { + return 1.0; +} + +prism::Rectangle platform::get_monitor_resolution() { + return {}; +} + +prism::Rectangle platform::get_monitor_work_area() { + return platform::get_monitor_resolution(); +} + +Window* get_window(const int index) { + for(auto& window : windows) { + if(window.identifier == index) + return &window; + } + + return nullptr; +} + +prism::Offset platform::get_window_position(const int index) { +} + +prism::Extent platform::get_window_size(const int index) { + auto window = get_window(index); + + int width, height; + SDL_GetWindowSize(window->window, &width, &height); + + return {(uint32_t)width, (uint32_t)height}; +} + +prism::Extent platform::get_window_drawable_size(const int index) { + auto window = get_window(index); + + int width, height; + SDL_GetWindowSize(window->window, &width, &height); + + return {(uint32_t)width, (uint32_t)height}; +} + +bool platform::is_window_focused(const int index) { +} + +void platform::set_window_focused(const int index) { +} + +void platform::set_window_position(const int index, const prism::Offset offset) { +} + +void platform::set_window_size(const int index, const prism::Extent extent) { +} + +void platform::set_window_title(const int index, const std::string_view title) { + auto window = get_window(index); + + SDL_SetWindowTitle(window->window, title.data()); +} + +bool platform::get_key_down(const InputButton key) { + return false; +} + +int platform::get_keycode(const InputButton key) { + return inputToKeyCode[key]; +} + +prism::Offset platform::get_cursor_position() { + return {0, 0}; +} + +prism::Offset platform::get_screen_cursor_position() { + return {0, 0}; +} + +bool platform::get_mouse_button_down(const int button) { + return false; +} + +std::tuple platform::get_wheel_delta() { +} + +std::tuple platform::get_right_stick_position() { +} + +std::tuple platform::get_left_stick_position() { +} + +void platform::capture_mouse(const bool capture) { +} + +void platform::open_dialog(const bool existing, std::function returnFunction, bool openDirectory) { +} + +void platform::save_dialog(std::function returnFunction) { +} + +char* platform::translate_keycode(const unsigned int keycode) { + return ""; +} + +int stdout_copy; +int stderr_copy; + +void platform::mute_output() { + +} + +void platform::unmute_output() { + +} + +int main(int argc, char* argv[]) { + SDL_Init(SDL_INIT_VIDEO); + + engine = new Engine(argc, argv); + + app = new @APP_CLASS@(); + engine->set_app(app); + + GFXCreateInfo info = {}; + + interface = new GFXVulkan(); + if(interface->initialize(info)) { + engine->set_gfx(interface); + } else { + return -1; + } + + app_main(engine); + + while(1) { + SDL_Event event = {}; + while(SDL_PollEvent(&event)) { + + } + + if(engine->is_quitting()) + break; + + engine->update(1.0 / 60.0); + engine->begin_frame(1.0 / 60.0); + engine->render(0); + + engine->end_frame(); + } + + return 0; +} + +PlatformTheme platform::get_theme() { + return PlatformTheme::Light; +} + +void* platform::create_native_surface(int index, void* instance) { + auto window = get_window(index); + + VkSurfaceKHR surface; + + SDL_Vulkan_CreateSurface(window->window, (VkInstance)instance, &surface); + + return surface; +} + +std::vector platform::get_native_surface_extension() { + // dummy window + auto dummy = SDL_CreateWindow("", 0, 0, 1, 1, SDL_WINDOW_VULKAN); + + unsigned int count = 0; + SDL_Vulkan_GetInstanceExtensions(dummy, &count, nullptr); + + std::vector extensions(count); + SDL_Vulkan_GetInstanceExtensions(dummy, &count, extensions.data()); + + SDL_DestroyWindow(dummy); + + return extensions; +}