Add experimental SDL backend for Linux
This commit is contained in:
parent
aac44f763c
commit
f0a1dc2f20
6 changed files with 295 additions and 22 deletions
|
@ -18,6 +18,12 @@
|
|||
#include "utility.hpp"
|
||||
#include "gfx_vulkan_commandbuffer.hpp"
|
||||
|
||||
#ifdef PLATFORM_LINUX
|
||||
#include <SDL2/SDL.h>
|
||||
#include <platform.hpp>
|
||||
|
||||
#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<VkExtensionProperties> extensionProperties(extensionPropertyCount);
|
||||
vkEnumerateInstanceExtensionProperties(nullptr, &extensionPropertyCount, extensionProperties.data());
|
||||
|
||||
std::vector<const char*> enabledExtensions = { "VK_KHR_surface", surface_name };
|
||||
std::vector<const char*> 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<WindowConnection*>(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
|
||||
|
||||
|
|
|
@ -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<const char*> get_native_surface_extension();
|
||||
|
||||
/** Closes a window.
|
||||
@param index The window to close.
|
||||
*/
|
||||
|
|
|
@ -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()
|
21
platforms/sdl/CMakeLists.txt
Normal file
21
platforms/sdl/CMakeLists.txt
Normal file
|
@ -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 $<TARGET_FILE_DIR:${target}>/data)
|
||||
endif()
|
||||
|
||||
add_custom_command(TARGET ${target} PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:${target}>/shaders)
|
||||
|
||||
add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/shaders $<TARGET_FILE_DIR:${target}>/shaders)
|
||||
endfunction()
|
11
platforms/sdl/file.cpp
Normal file
11
platforms/sdl/file.cpp
Normal file
|
@ -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 "~";
|
||||
}
|
243
platforms/sdl/main.cpp.in
Normal file
243
platforms/sdl/main.cpp.in
Normal file
|
@ -0,0 +1,243 @@
|
|||
#include <@APP_INCLUDE@>
|
||||
#include <engine.hpp>
|
||||
|
||||
#include "gfx_vulkan.hpp"
|
||||
#include "platform.hpp"
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_vulkan.h>
|
||||
|
||||
@APP_CLASS@* app = nullptr;
|
||||
GFX* interface = nullptr;
|
||||
|
||||
struct Window {
|
||||
int identifier = 0;
|
||||
SDL_Window* window = nullptr;
|
||||
};
|
||||
|
||||
std::vector<Window> windows;
|
||||
|
||||
static std::map<InputButton, int> 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<float, float> platform::get_wheel_delta() {
|
||||
}
|
||||
|
||||
std::tuple<float, float> platform::get_right_stick_position() {
|
||||
}
|
||||
|
||||
std::tuple<float, float> platform::get_left_stick_position() {
|
||||
}
|
||||
|
||||
void platform::capture_mouse(const bool capture) {
|
||||
}
|
||||
|
||||
void platform::open_dialog(const bool existing, std::function<void(std::string)> returnFunction, bool openDirectory) {
|
||||
}
|
||||
|
||||
void platform::save_dialog(std::function<void(std::string)> 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<const char*> 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<const char*> extensions(count);
|
||||
SDL_Vulkan_GetInstanceExtensions(dummy, &count, extensions.data());
|
||||
|
||||
SDL_DestroyWindow(dummy);
|
||||
|
||||
return extensions;
|
||||
}
|
Reference in a new issue