diff --git a/libs/app/CMakeLists.txt b/libs/app/CMakeLists.txt index b13b1149..51e5ea78 100644 --- a/libs/app/CMakeLists.txt +++ b/libs/app/CMakeLists.txt @@ -1,5 +1,3 @@ -find_package(SDL2 REQUIRED) - file(GLOB_RECURSE PSEMEK_APP_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp") file(GLOB_RECURSE PSEMEK_APP_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "source/*.cpp") diff --git a/libs/app/source/app.cpp b/libs/app/source/app.cpp index 1927cc49..54141376 100644 --- a/libs/app/source/app.cpp +++ b/libs/app/source/app.cpp @@ -1,43 +1,20 @@ #include #include #include +#include #include namespace psemek::app { - namespace - { - - [[noreturn]] void sdl_fail(std::string const & message) - { - throw std::runtime_error(message + SDL_GetError()); - } - - struct sdl_initializer - { - sdl_initializer() - { - if (SDL_Init(SDL_INIT_VIDEO) != 0) - sdl_fail("Failed to initialize SDL2: "); - } - - ~sdl_initializer() - { - SDL_Quit(); - } - }; - - } - using clock = std::chrono::high_resolution_clock; struct app::impl { app * parent; - sdl_initializer init; + std::shared_ptr sdl_init; SDL_Window * window = nullptr; SDL_GLContext gl_context = nullptr; @@ -51,6 +28,7 @@ namespace psemek::app impl(app * parent) : parent(parent) + , sdl_init(sdl2::init(SDL_INIT_VIDEO)) {} ~impl() @@ -97,11 +75,11 @@ namespace psemek::app impl().window = SDL_CreateWindow(name.data(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_MAXIMIZED); if (!impl().window) - sdl_fail("Failed to create window: "); + sdl2::fail("Failed to create window: "); impl().gl_context = SDL_GL_CreateContext(impl().window); if (!impl().gl_context) - sdl_fail("Failed to create OpenGL context: "); + sdl2::fail("Failed to create OpenGL context: "); SDL_GL_MakeCurrent(impl().window, impl().gl_context); diff --git a/libs/sdl2/CMakeLists.txt b/libs/sdl2/CMakeLists.txt new file mode 100644 index 00000000..cfee727d --- /dev/null +++ b/libs/sdl2/CMakeLists.txt @@ -0,0 +1,8 @@ +find_package(SDL2 REQUIRED) + +file(GLOB_RECURSE PSEMEK_SDL2_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp") +file(GLOB_RECURSE PSEMEK_SDL2_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "source/*.cpp") + +add_library(psemek-sdl2 ${PSEMEK_SDL2_HEADERS} ${PSEMEK_SDL2_SOURCES}) +target_include_directories(psemek-sdl2 PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${SDL2_INCLUDE_DIRS}") +target_link_libraries(psemek-sdl2 PUBLIC ${SDL2_LIBRARIES}) diff --git a/libs/sdl2/include/psemek/sdl2/init.hpp b/libs/sdl2/include/psemek/sdl2/init.hpp new file mode 100644 index 00000000..f5cd721c --- /dev/null +++ b/libs/sdl2/include/psemek/sdl2/init.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +namespace psemek::sdl2 +{ + + [[noreturn]] void fail(std::string const & message); + + std::shared_ptr init(std::uint32_t subsystems); + +} diff --git a/libs/sdl2/source/init.cpp b/libs/sdl2/source/init.cpp new file mode 100644 index 00000000..a8c9fdf2 --- /dev/null +++ b/libs/sdl2/source/init.cpp @@ -0,0 +1,68 @@ +#include + +#include + +namespace psemek::sdl2 +{ + + namespace + { + + struct sdl_initializer + { + sdl_initializer() + { + if (SDL_Init(0) != 0) + fail("Failed to initialize SDL2: "); + } + + ~sdl_initializer() + { + SDL_Quit(); + } + + static std::shared_ptr instance() + { + static std::weak_ptr ptr; + + if (auto p = ptr.lock(); p) + return p; + + auto p = std::make_shared(); + ptr = p; + return p; + } + }; + + struct subsystem_initializer + { + std::shared_ptr sdl_init; + std::uint32_t subsystems; + + subsystem_initializer(std::uint32_t subsystems) + : sdl_init(sdl_initializer::instance()) + , subsystems(subsystems) + { + if (SDL_InitSubSystem(subsystems) != 0) + fail("Failed to initialize SDL2 subsystems: "); + } + + ~subsystem_initializer() + { + SDL_QuitSubSystem(subsystems); + } + }; + + } + + [[noreturn]] void fail(std::string const & message) + { + throw std::runtime_error(message + SDL_GetError()); + } + + std::shared_ptr init(std::uint32_t subsystems) + { + return std::make_shared(subsystems); + } + +}