Merge pull request 'feat/165-gui' (#168) from feat/165-gui into main

Reviewed-on: #168
This commit is contained in:
falsycat 2023-09-30 05:31:20 +00:00
commit ab9e7f4a3d
17 changed files with 499 additions and 214 deletions

View File

@ -6,6 +6,7 @@ target_link_libraries(nf7_core
luajit
nf7_config
nf7_iface
OpenGL
SDL2
sqlite
uvw
@ -13,6 +14,7 @@ target_link_libraries(nf7_core
target_sources(nf7_core
PRIVATE
gl3/context.cc
imgui/context.cc
luajit/context.cc
luajit/lambda.cc
luajit/thread.cc
@ -22,6 +24,8 @@ target_sources(nf7_core
version.cc
PUBLIC
gl3/context.hh
imgui/context.hh
imgui/driver.hh
luajit/context.hh
luajit/lambda.hh
luajit/thread.hh
@ -44,6 +48,9 @@ add_executable(nf7_core_test)
target_sources(nf7_core_test
PRIVATE
gl3/context_test.cc
imgui/context_test.cc
imgui/context_test.hh
imgui/driver_test.hh
luajit/context_test.cc
luajit/context_test.hh
luajit/lambda_test.cc

View File

@ -7,6 +7,7 @@
#include <atomic>
#include <chrono>
#include <cstdlib>
#include <functional>
#include <memory>
#include <thread>
#include <typeindex>
@ -24,15 +25,22 @@ namespace nf7::core::test {
class EnvFixture : public ::testing::Test {
public:
EnvFixture() = delete;
explicit EnvFixture(SimpleEnv::FactoryMap&& fmap) noexcept
: fmap_(std::move(fmap)) { }
EnvFixture() = default;
protected:
template <typename I>
void Install(const std::shared_ptr<I>& o) {
fmap_.emplace(typeid(I), [o](auto&) { return o; });
}
template <typename I>
void Install(std::function<std::shared_ptr<I>(Env&)>&& factory) {
fmap_.emplace(typeid(I), std::move(factory));
}
template <typename I, typename T>
void Install() {
fmap_.emplace(
typeid(I), [](auto& env) { return std::make_shared<T>(env); });
}
protected:
void SetUp() override {
@ -120,9 +128,8 @@ class EnvFixtureWithTasking : public EnvFixture {
};
public:
explicit EnvFixtureWithTasking(SimpleEnv::FactoryMap&& fmap = {})
: EnvFixture(std::move(fmap)),
clock_(std::make_shared<Clock>()),
EnvFixtureWithTasking()
: clock_(std::make_shared<Clock>()),
sq_(std::make_shared<SimpleTaskQueue<SyncTask>>()),
aq_(std::make_shared<SimpleTaskQueue<AsyncTask>>()),
ad_(*this) {

View File

@ -2,6 +2,8 @@
#include "core/gl3/context.hh"
#include "iface/common/exception.hh"
#include "iface/subsys/clock.hh"
#include "iface/subsys/logger.hh"
#include "iface/subsys/parallelism.hh"
#include "core/logger.hh"
@ -11,138 +13,151 @@ using namespace std::literals;
namespace nf7::core::gl3 {
Context::Context(Env& env, const std::shared_ptr<Impl>& impl)
class Context::Impl : public std::enable_shared_from_this<Impl> {
private:
static constexpr const auto kPollingInterval = 17ms;
public:
Impl(Env& env, Context& ctx)
try : clock_(env.Get<subsys::Clock>()),
concurrency_(env.Get<subsys::Concurrency>()),
logger_(env.GetOr<subsys::Logger>(NullLogger::kInstance)),
ctx_(&ctx) {
sdl_ = 0 == SDL_Init(SDL_INIT_VIDEO);
if (!sdl_) {
throw Exception {"SDL init failure"};
}
SetUpGL();
SetUpWindow();
} catch (const Exception&) {
TearDown();
throw;
}
public:
virtual ~Impl() = default;
Impl(const Impl&) = delete;
Impl(Impl&&) = delete;
Impl& operator=(const Impl&) = delete;
Impl& operator=(Impl&&) = delete;
public:
TaskContext MakeContext() const noexcept {
return TaskContext {win_, gl_};
}
void SchedulePolling() noexcept {
if (nullptr != ctx_) {
concurrency_->Push(nf7::SyncTask {
clock_->now() + kPollingInterval,
[this, self = shared_from_this()](auto&) { Poll(); },
});
}
}
void ScheduleTearDown() noexcept {
ctx_ = nullptr;
concurrency_->Exec(
[this, self = shared_from_this()](auto&) { TearDown(); });
}
void Push(Task&& task) noexcept {
const auto after = task.after();
concurrency_->Push(SyncTask {
after,
[this, self = shared_from_this(), task = std::move(task)](auto&) mutable {
auto ctx = MakeContext();
task(ctx);
},
});
}
private:
void Poll() noexcept {
SDL_Event e;
while (SDL_PollEvent(&e)) {
if (nullptr != ctx_) {
ctx_->Notify(SDL_Event {e});
}
}
SchedulePolling();
}
private:
void SetUpGL() noexcept {
# if defined(__APPLE__)
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
# else
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
# endif
}
void SetUpWindow() {
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
constexpr auto flags {
SDL_WINDOW_OPENGL
| SDL_WINDOW_RESIZABLE
| SDL_WINDOW_ALLOW_HIGHDPI
};
win_ = SDL_CreateWindow(
"Dear ImGui SDL2+OpenGL3 example",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
1280, 720,
flags);
if (nullptr == win_) {
throw Exception {"failed to create new window"};
}
gl_ = SDL_GL_CreateContext(win_);
if (nullptr == gl_) {
throw Exception {"failed to create new GL context"};
}
SDL_GL_SetSwapInterval(0);
}
void TearDown() noexcept {
if (nullptr != gl_) {
SDL_GL_DeleteContext(gl_);
}
if (nullptr != win_) {
SDL_DestroyWindow(win_);
}
if (sdl_) {
SDL_Quit();
}
}
private:
const std::shared_ptr<subsys::Clock> clock_;
const std::shared_ptr<subsys::Concurrency> concurrency_;
const std::shared_ptr<subsys::Logger> logger_;
Context* ctx_;
bool sdl_ {false};
SDL_Window* win_ {nullptr};
void* gl_ {nullptr};
};
Context::Context(Env& env)
try : subsys::Interface("nf7::core::gl3::Context"),
impl_(impl? impl: std::make_shared<Impl>(env)) {
impl_->Main();
impl_(std::make_shared<Impl>(env, *this)) {
impl_->SchedulePolling();
} catch (const std::bad_alloc&) {
throw MemoryException {};
}
Context::~Context() noexcept {
impl_->Exit();
impl_->ScheduleTearDown();
}
void Context::Push(Task&& task) noexcept {
impl_->Push(std::move(task));
}
class Context::Impl::TaskDriver final {
public:
TaskDriver() = delete;
explicit TaskDriver(const std::shared_ptr<subsys::Logger>& logger,
Task::Time time) noexcept
: logger_(logger), time_(time) { }
public:
void BeginBusy() noexcept { }
void EndBusy() noexcept { }
void Drive(Task&& task) noexcept
try {
task(ctx_);
} catch (Exception& e) {
logger_->Warn("GL3 task caused an exception");
}
public:
Task::Time tick() const noexcept { return time_; }
bool nextIdleInterruption() const noexcept { return true; }
bool nextTaskInterruption() const noexcept { return false; }
private:
const std::shared_ptr<subsys::Logger> logger_;
const Task::Time time_;
TaskContext ctx_ {};
};
Context::Impl::Impl(Env& env)
try : clock_(env.Get<subsys::Clock>()),
concurrency_(env.Get<subsys::Concurrency>()),
logger_(env.GetOr<subsys::Logger>(NullLogger::kInstance)) {
sdl_ = 0 == SDL_Init(SDL_INIT_VIDEO);
if (!sdl_) {
throw Exception {"SDL init failure"};
}
SetUpGL();
SetUpWindow();
} catch (const Exception&) {
TearDown();
throw;
}
void Context::Impl::Main() noexcept {
const bool alive = Update();
const auto now = clock_->now();
TaskDriver driver {logger_, now};
tasq_.Drive(driver);
if (alive_ && alive) {
concurrency_->Push(nf7::SyncTask {
now + 33ms,
[wself = weak_from_this()](auto&) {
if (auto self = wself.lock()) { self->Main(); }
},
});
} else {
TearDown();
}
}
void Context::Impl::SetUpGL() noexcept {
# if defined(__APPLE__)
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
# else
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
# endif
}
void Context::Impl::SetUpWindow() {
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
constexpr auto flags {
SDL_WINDOW_OPENGL
| SDL_WINDOW_RESIZABLE
| SDL_WINDOW_ALLOW_HIGHDPI
};
win_ = SDL_CreateWindow(
"Dear ImGui SDL2+OpenGL3 example",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
1280, 720,
flags);
if (nullptr == win_) {
throw Exception {"failed to create new window"};
}
gl_ = SDL_GL_CreateContext(win_);
if (nullptr == gl_) {
throw Exception {"failed to create new GL context"};
}
SDL_GL_SetSwapInterval(0);
}
void Context::Impl::TearDown() noexcept {
if (nullptr != gl_) {
SDL_GL_DeleteContext(gl_);
}
if (nullptr != win_) {
SDL_DestroyWindow(win_);
}
if (sdl_) {
SDL_Quit();
}
}
} // namespace nf7::core::gl3

View File

@ -6,10 +6,9 @@
#include <memory>
#include <utility>
#include "iface/subsys/clock.hh"
#include "iface/common/observer.hh"
#include "iface/subsys/concurrency.hh"
#include "iface/subsys/interface.hh"
#include "iface/subsys/logger.hh"
#include "iface/env.hh"
@ -17,19 +16,32 @@ namespace nf7::core::gl3 {
class TaskContext final {
public:
TaskContext() = default;
TaskContext() = delete;
TaskContext(SDL_Window* win, void* gl) noexcept
: win_(win), gl_(gl) { }
TaskContext(const TaskContext&) = delete;
TaskContext(TaskContext&&) = delete;
TaskContext& operator=(const TaskContext&) = delete;
TaskContext& operator=(TaskContext&&) = delete;
public:
SDL_Window* win() const noexcept { return win_; }
void* gl() const noexcept { return gl_; }
private:
SDL_Window* const win_;
void* const gl_;
};
using Task = nf7::Task<TaskContext&>;
using TaskQueue = nf7::TaskQueue<Task>;
class Context : public subsys::Interface, public TaskQueue {
class Context :
public subsys::Interface,
public Observer<SDL_Event>::Target,
public TaskQueue {
public:
# if defined(__APPLE__)
static constexpr const char* kGlslVersion = "#version 150";
@ -41,67 +53,15 @@ class Context : public subsys::Interface, public TaskQueue {
class Impl;
public:
explicit Context(
Env&,
const std::shared_ptr<Impl>& = nullptr);
explicit Context(Env&);
~Context() noexcept override;
public:
// THREAD-SAFE
void Push(Task&&) noexcept override;
private:
const std::shared_ptr<Impl> impl_;
};
class Context::Impl : public std::enable_shared_from_this<Impl> {
public:
class TaskDriver;
friend class Context;
public:
explicit Impl(Env&);
virtual ~Impl() = default;
Impl(const Impl&) = delete;
Impl(Impl&&) = delete;
Impl& operator=(const Impl&) = delete;
Impl& operator=(Impl&&) = delete;
protected:
virtual bool Update() noexcept {
SDL_Event ev;
while (SDL_PollEvent(&ev)) { }
SDL_GL_MakeCurrent(win_, gl_);
SDL_GL_SwapWindow(win_);
return true;
}
protected:
SDL_Window* win() const noexcept { return win_; }
void* gl() const noexcept { return gl_; }
private:
void Exit() noexcept { alive_ = false; }
void Push(Task&& task) noexcept { tasq_.Push(std::move(task)); }
void Main() noexcept;
private:
void SetUpGL() noexcept;
void SetUpWindow();
void TearDown() noexcept;
private:
const std::shared_ptr<subsys::Clock> clock_;
const std::shared_ptr<subsys::Concurrency> concurrency_;
const std::shared_ptr<subsys::Logger> logger_;
nf7::SimpleTaskQueue<Task> tasq_;
bool alive_ {true};
bool sdl_ {false};
SDL_Window* win_ {nullptr};
void* gl_ {nullptr};
};
} // namespace nf7::core::gl3

View File

@ -5,6 +5,8 @@
#include <gtest/gtest.h>
#include <memory>
#include "iface/env.hh"
#include "core/env_test.hh"
@ -15,12 +17,11 @@ namespace nf7::core::gl3::test {
class ContextFixture : public nf7::core::test::EnvFixtureWithTasking {
public:
ContextFixture() noexcept
: EnvFixtureWithTasking({
nf7::SimpleEnv::MakePair<Context, Context>(),
}),
skip_(nullptr == std::getenv("NF7_TEST_GL3")) { }
: skip_(nullptr == std::getenv("NF7_TEST_GL3")) {
Install<Context, Context>();
}
public:
protected:
void SetUp() override {
if (skip_) {
GTEST_SKIP();

163
core/imgui/context.cc Normal file
View File

@ -0,0 +1,163 @@
// No copyright
#include "core/imgui/context.hh"
#include <SDL_opengl.h>
#include <imgui_impl_opengl3.h>
#include <imgui_impl_sdl2.h>
#include <chrono>
#include <utility>
#include <vector>
#include <iostream>
#include "iface/common/exception.hh"
#include "iface/common/observer.hh"
#include "iface/subsys/clock.hh"
#include "core/gl3/context.hh"
namespace nf7::core::imgui {
class Context::Impl final : public std::enable_shared_from_this<Impl> {
private:
static constexpr auto kUpdateInterval = std::chrono::milliseconds {33};
private:
class EventQueue final : public Observer<SDL_Event> {
public:
using Observer<SDL_Event>::Observer;
public:
EventQueue(const EventQueue&) = delete;
EventQueue(EventQueue&&) = delete;
EventQueue& operator=(const EventQueue&) = delete;
EventQueue& operator=(EventQueue&&) = delete;
public:
std::vector<SDL_Event> Take() noexcept { return std::move(items_); }
private:
void Notify(const SDL_Event& e) noexcept override { items_.push_back(e); }
private:
std::vector<SDL_Event> items_;
};
public:
explicit Impl(Env& env)
: clock_(env.Get<subsys::Clock>()),
gl3_(env.Get<gl3::Context>()),
events_(std::make_unique<EventQueue>(*gl3_)),
imgui_(ImGui::CreateContext()) {
}
Impl(const Impl&) = delete;
Impl(Impl&&) = delete;
Impl& operator=(const Impl&) = delete;
Impl& operator=(Impl&&) = delete;
public:
void ScheduleStart() noexcept {
gl3_->Exec([this, self = shared_from_this()](auto& t) { Start(t); });
}
void ScheduleTearDown() noexcept {
gl3_->Exec([this, self = shared_from_this()](auto& t) { TearDown(t); });
}
const std::shared_ptr<Driver>& Register(const std::shared_ptr<Driver>& driver)
try {
drivers_.emplace_back(driver);
return driver;
} catch (const std::bad_alloc&) {
throw MemoryException {};
}
private:
void Start(gl3::TaskContext& t) noexcept {
ImGui::SetCurrentContext(imgui_);
ImGui_ImplSDL2_InitForOpenGL(t.win(), t.gl());
ImGui_ImplOpenGL3_Init(gl3::Context::kGlslVersion);
Update(t);
}
void Update(gl3::TaskContext& t) noexcept {
ImGui::SetCurrentContext(imgui_);
// get active drivers and drop dead ones
std::vector<std::shared_ptr<Driver>> drivers;
for (auto itr = drivers_.begin(); itr != drivers_.end();) {
if (auto driver = itr->lock()) {
drivers.emplace_back(std::move(driver));
++itr;
} else {
itr = drivers_.erase(itr);
}
}
// event handling
const auto events = events_->Take();
for (const auto& event : events) {
ImGui_ImplSDL2_ProcessEvent(&event);
}
// frame reset
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
// draw something
for (const auto& driver : drivers) { driver->Update(t); }
ImGui::Render();
// render them
const auto& io = ImGui::GetIO();
glViewport(0, 0,
static_cast<int>(io.DisplaySize.x),
static_cast<int>(io.DisplaySize.y));
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
for (const auto& driver : drivers) { driver->PreUpdate(t); }
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
for (const auto& driver : drivers) { driver->PostUpdate(t); }
SDL_GL_SwapWindow(t.win());
// schedule next frame
gl3_->Push(gl3::Task {
clock_->now() + kUpdateInterval,
[wself = weak_from_this()](auto& t) {
if (auto self = wself.lock()) { self->Update(t); }
},
});
}
void TearDown(gl3::TaskContext&) noexcept {
ImGui::SetCurrentContext(imgui_);
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext(imgui_);
}
private:
const std::shared_ptr<subsys::Clock> clock_;
const std::shared_ptr<gl3::Context> gl3_;
const std::unique_ptr<EventQueue> events_;
ImGuiContext* const imgui_;
std::vector<std::weak_ptr<Driver>> drivers_;
};
Context::Context(Env& env)
try : subsys::Interface("nf7::core::imgui::Context"),
impl_(std::make_shared<Impl>(env)) {
impl_->ScheduleStart();
} catch (const std::bad_alloc&) {
throw MemoryException {};
}
Context::~Context() noexcept {
impl_->ScheduleTearDown();
}
const std::shared_ptr<Driver>& Context::Register(
const std::shared_ptr<Driver>& driver) {
return impl_->Register(driver);
}
} // namespace nf7::core::imgui

31
core/imgui/context.hh Normal file
View File

@ -0,0 +1,31 @@
// No copyright
#pragma once
#include <imgui.h>
#include <memory>
#include "iface/env.hh"
#include "core/imgui/driver.hh"
namespace nf7::core::imgui {
class Context : public subsys::Interface {
private:
class Impl;
public:
explicit Context(Env&);
~Context() noexcept override;
public:
const std::shared_ptr<Driver>& Register(
const std::shared_ptr<Driver>& driver);
private:
const std::shared_ptr<Impl> impl_;
};
} // namespace nf7::core::imgui

View File

@ -0,0 +1,38 @@
// No copyright
#include "core/imgui/context.hh"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <imgui.h>
#include <chrono>
#include "core/imgui/context_test.hh"
#include "core/imgui/driver_test.hh"
// adds meaningless suffix to avoid a conflict with ImGuiContext
using ImGuiContext0 = nf7::core::imgui::test::ContextFixture;
TEST_F(ImGuiContext0, Init) {
const auto clock = env().Get<nf7::subsys::Clock>();
const auto concurrency = env().Get<nf7::subsys::Concurrency>();
auto ctx = env().Get<nf7::core::imgui::Context>();
concurrency->Push(nf7::SyncTask {
clock->now() + std::chrono::seconds {10},
[&](auto&) { ctx = nullptr; },
});
auto driver = std::make_shared<
::testing::NiceMock<nf7::core::imgui::test::DriverMock>>();
ctx->Register(driver);
bool shown = true;
ON_CALL(*driver, Update).WillByDefault([&](auto&) {
ImGui::ShowDemoWindow(&shown);
});
DropEnv();
ConsumeTasks();
}

View File

@ -0,0 +1,16 @@
// No copyright
#pragma once
#include <memory>
#include "core/gl3/context_test.hh"
namespace nf7::core::imgui::test {
class ContextFixture : public gl3::test::ContextFixture {
public:
ContextFixture() { Install<Context, Context>(); }
};
} // namespace nf7::core::imgui::test

25
core/imgui/driver.hh Normal file
View File

@ -0,0 +1,25 @@
// No copyright
#pragma once
#include "core/gl3/context.hh"
namespace nf7::core::imgui {
class Driver {
public:
Driver() = default;
virtual ~Driver() = default;
Driver(const Driver&) = delete;
Driver(Driver&&) = delete;
Driver& operator=(const Driver&) = delete;
Driver& operator=(Driver&&) = delete;
public:
virtual void PreUpdate(gl3::TaskContext&) noexcept { }
virtual void Update(gl3::TaskContext&) noexcept { }
virtual void PostUpdate(gl3::TaskContext&) noexcept { }
};
} // namespace nf7::core::imgui

22
core/imgui/driver_test.hh Normal file
View File

@ -0,0 +1,22 @@
// No copyright
#pragma once
#include "core/imgui/driver.hh"
#include <gmock/gmock.h>
#include "core/gl3/context.hh"
namespace nf7::core::imgui::test {
class DriverMock : public Driver {
public:
using Driver::Driver;
MOCK_METHOD(void, PreUpdate, (gl3::TaskContext&), (noexcept, override));
MOCK_METHOD(void, Update, (gl3::TaskContext&), (noexcept, override));
MOCK_METHOD(void, PostUpdate, (gl3::TaskContext&), (noexcept, override));
};
} // namespace nf7::core::imgui::test

View File

@ -159,7 +159,7 @@ class AsyncContext final :
};
} // namespace
std::shared_ptr<Context> Context::Create(Env& env, Kind kind) {
std::shared_ptr<Context> Context::Make(Env& env, Kind kind) {
switch (kind) {
case kSync:
return std::make_shared<SyncContext>(env);

View File

@ -147,7 +147,13 @@ class Context :
kSync,
kAsync,
};
static std::shared_ptr<Context> Create(Env&, Kind);
static std::shared_ptr<Context> Make(Env&, Kind);
static std::shared_ptr<Context> MakeAsync(Env& env) {
return Make(env, kAsync);
}
static std::shared_ptr<Context> MakeSync(Env& env) {
return Make(env, kSync);
}
explicit Context(const char* name, Kind kind)
: subsys::Interface(name), kind_(kind), state_(nullptr) {

View File

@ -26,14 +26,9 @@ class ContextFixture :
public nf7::core::test::EnvFixtureWithTasking,
public ::testing::WithParamInterface<Context::Kind> {
public:
ContextFixture() noexcept
: EnvFixtureWithTasking({
{
typeid(Context), [](auto& env) {
return Context::Create(env, GetParam());
},
},
}) { }
ContextFixture() {
Install<Context>([](auto& env) { return Context::Make(env, GetParam()); });
}
};
} // namespace nf7::core::luajit::test

View File

@ -15,12 +15,9 @@ namespace nf7::core::sqlite::test {
class DatabaseFixture : public nf7::core::test::EnvFixtureWithTasking {
public:
DatabaseFixture()
: nf7::core::test::EnvFixtureWithTasking({
{typeid(nf7::subsys::Database), [](auto& env) {
return std::make_shared<Database>(env, ":memory:");
}},
}) {
DatabaseFixture() {
Install<subsys::Database>(
[](auto& env) { return std::make_shared<Database>(env, ":memory:"); });
}
};

View File

@ -20,11 +20,9 @@ namespace nf7::core::uv::test {
class ContextFixture : public nf7::core::test::EnvFixture {
public:
ContextFixture() noexcept
: nf7::core::test::EnvFixture({
SimpleEnv::MakePair<Context, MainContext>(),
SimpleEnv::MakePair<subsys::Clock, Clock>(),
}) {
ContextFixture() {
Install<Context, MainContext>();
Install<subsys::Clock, Clock>();
}
protected:

View File

@ -29,6 +29,10 @@ FetchContent_Declare(
FetchContent_Populate(luajit)
include(luajit.cmake)
# ---- OpenGL
find_package(OpenGL REQUIRED GLOBAL)
add_library(OpenGL ALIAS OpenGL::GL)
# ---- SDL2 (zlib)
find_package(SDL2 REQUIRED GLOBAL)
add_library(SDL2 ALIAS SDL2::SDL2)