Add SDL2 initialization library & use it in app

This commit is contained in:
Nikita Lisitsa 2020-09-21 09:05:21 +03:00
parent d2d88ba7c5
commit dbfd9da21c
5 changed files with 94 additions and 29 deletions

View file

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

View file

@ -1,43 +1,20 @@
#include <psemek/app/app.hpp>
#include <psemek/gfx/gl.hpp>
#include <psemek/log/log.hpp>
#include <psemek/sdl2/init.hpp>
#include <SDL2/SDL.h>
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<void> 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);

8
libs/sdl2/CMakeLists.txt Normal file
View file

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

View file

@ -0,0 +1,13 @@
#pragma once
#include <memory>
#include <cstdint>
namespace psemek::sdl2
{
[[noreturn]] void fail(std::string const & message);
std::shared_ptr<void> init(std::uint32_t subsystems);
}

68
libs/sdl2/source/init.cpp Normal file
View file

@ -0,0 +1,68 @@
#include <psemek/sdl2/init.hpp>
#include <SDL2/SDL.h>
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<sdl_initializer> instance()
{
static std::weak_ptr<sdl_initializer> ptr;
if (auto p = ptr.lock(); p)
return p;
auto p = std::make_shared<sdl_initializer>();
ptr = p;
return p;
}
};
struct subsystem_initializer
{
std::shared_ptr<sdl_initializer> 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<void> init(std::uint32_t subsystems)
{
return std::make_shared<subsystem_initializer>(subsystems);
}
}