Archived
1
Fork 0

Add experimental SDL backend for Linux

This commit is contained in:
redstrate 2021-03-01 14:40:02 -05:00
parent aac44f763c
commit f0a1dc2f20
6 changed files with 295 additions and 22 deletions

View file

@ -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

View file

@ -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.
*/

View file

@ -3,7 +3,7 @@ if(ENABLE_WINDOWS)
endif()
if(ENABLE_LINUX)
add_subdirectory(linux)
add_subdirectory(sdl)
endif()
if(ENABLE_MACOS)

View 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
View 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
View 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;
}