149 lines
7.1 KiB
C++
149 lines
7.1 KiB
C++
#pragma once
|
|
#include <algorithm>
|
|
#include <concepts>
|
|
#include <cstddef>
|
|
#include <memory>
|
|
#include <memory_resource>
|
|
#include <utility>
|
|
#include "renderive/base/observer/Observer.hpp"
|
|
#include "renderive/frame_control/Frame_Control.hpp"
|
|
#include "renderive/renderable/color/Concepts.hpp"
|
|
#include "renderive/state/Published_State_Storage.hpp"
|
|
#include "renderive/scene/base/Scene_Base.hpp"
|
|
#include "renderive/scene/base/Frame_Viewport.hpp"
|
|
struct Scene2D_Frame_Data : Abstract_Frame {};
|
|
struct Scene2D_State {
|
|
Frame_Viewport viewport;
|
|
};
|
|
template <class State>
|
|
concept Scene2D_State_Value = State_Value<State> && requires(State& state) {
|
|
requires std::same_as<std::remove_cvref_t<decltype(state.viewport)>, Frame_Viewport>;
|
|
};
|
|
template <class Frame_Control, class... Args>
|
|
concept Scene2D_Frame_Control_Constructible = std::constructible_from<Frame_Control, Args...> || std::constructible_from<Frame_Control, std::pmr::memory_resource&, Args...>;
|
|
template <class Strategy = Low_Latency_Strategy<Scene2D_Frame_Data>, Color_Cache_Type Cache = Recording_Color_Cache, class State = Scene2D_State, class State_Observer = Observer_State<>, class Scene_Observer = Observer_State<>>
|
|
requires Frame_Control_Strategy_For<Strategy, Scene2D_Frame_Data> && Scene2D_State_Value<State>
|
|
class Scene2D_Context : public Scene_2D_Base,
|
|
public Published_State_Storage<State, Atomic_Spin_Mutex,
|
|
State_Observer>,
|
|
public Scene_Compositor {
|
|
public:
|
|
using Scene_State_Strategy =
|
|
Published_State_Storage<State, Atomic_Spin_Mutex, State_Observer>;
|
|
using Frame_Control = Strategy;
|
|
using Frame = typename Frame_Control::Frame;
|
|
using Painter_Lease = typename Frame_Control::Painter_Lease;
|
|
using Render_Lease = typename Frame_Control::Render_Lease;
|
|
template <class... Args>
|
|
requires Scene2D_Frame_Control_Constructible<Frame_Control, Args&&...>
|
|
explicit Scene2D_Context(Args&&... args) : Scene2D_Context(*std::pmr::get_default_resource(), std::forward<Args>(args)...) {}
|
|
template <class... Args>
|
|
requires Scene2D_Frame_Control_Constructible<Frame_Control, Args&&...>
|
|
explicit Scene2D_Context(std::pmr::memory_resource& memory_resource, Args&&... args)
|
|
: Scene_2D_Base(memory_resource, std::make_unique<Impl>()),
|
|
Scene_State_Strategy(State{}), frame_control(make_frame_control(this->memory_resource(), std::forward<Args>(args)...)), final_color_cache_(make_cache(this->memory_resource())) {}
|
|
template <class... Args>
|
|
requires Scene2D_Frame_Control_Constructible<Frame_Control, Args&&...>
|
|
Scene2D_Context(With_Observer<State_Observer> state_observer, With_Observer<Scene_Observer> scene_observer, Args&&... args)
|
|
: Scene2D_Context(*std::pmr::get_default_resource(), std::move(state_observer), std::move(scene_observer), std::forward<Args>(args)...) {}
|
|
template <class... Args>
|
|
requires Scene2D_Frame_Control_Constructible<Frame_Control, Args&&...>
|
|
Scene2D_Context(std::pmr::memory_resource& memory_resource, With_Observer<State_Observer> state_observer, With_Observer<Scene_Observer> scene_observer, Args&&... args)
|
|
: Scene_2D_Base(
|
|
memory_resource,
|
|
std::make_unique<Impl>(std::move(scene_observer.observer))),
|
|
Scene_State_Strategy(State{}, std::move(state_observer)), frame_control(make_frame_control(this->memory_resource(), std::forward<Args>(args)...)), final_color_cache_(make_cache(this->memory_resource())) {}
|
|
~Scene2D_Context() override {
|
|
this->shutdown();
|
|
}
|
|
Frame_Control frame_control;
|
|
template <class Function>
|
|
void with_final_color_cache(Function&& function) {
|
|
if (this->is_render_execution_context()) {
|
|
function(static_cast<const Cache&>(final_color_cache_));
|
|
return;
|
|
}
|
|
auto lock = this->lock_render_idle();
|
|
function(static_cast<const Cache&>(final_color_cache_));
|
|
}
|
|
protected:
|
|
Frame_Control_Strategy_Base& frame_control_strategy_impl() noexcept override {
|
|
return frame_control;
|
|
}
|
|
const Frame_Control_Strategy_Base& frame_control_strategy_impl() const noexcept override {
|
|
return frame_control;
|
|
}
|
|
std::shared_ptr<Color_Cache> make_renderable_color_cache() override {
|
|
return make_cache_pointer(this->memory_resource());
|
|
}
|
|
Frame_Viewport frame_viewport() const override {
|
|
return this->Scene_State_Strategy::render_state_value().viewport;
|
|
}
|
|
void begin_composite(const Composite_Render_Context&) override {
|
|
final_color_cache_.clear();
|
|
}
|
|
void composite(const Composite_Render_Context& context) override {
|
|
if (context.renderable && context.renderable->visible && context.color_cache)
|
|
final_color_cache_.composite(*context.color_cache);
|
|
}
|
|
void publish_scene_state() override {
|
|
this->Scene_State_Strategy::publish();
|
|
}
|
|
std::uint64_t acquire_scene_state() override {
|
|
return this->Scene_State_Strategy::state_revision();
|
|
}
|
|
void capture_scene_state(Frame_Render_Snapshot& snapshot) const override {
|
|
snapshot.set_scene_state(
|
|
this->Scene_State_Strategy::render_state_value());
|
|
}
|
|
private:
|
|
struct Context_State_Layer
|
|
: renderive::scene_inheritance::State_Node<
|
|
Context_State_Layer, Scene_2D_Base::State_Layer> {};
|
|
|
|
struct Impl
|
|
: renderive::scene_inheritance::Impl_Node<Impl, Scene_2D_Base::Impl> {
|
|
struct Observer
|
|
: renderive::scene_inheritance::Observer_Node<
|
|
Impl, Scene_2D_Base::Impl::Observer> {
|
|
static void handle(Impl& layer,
|
|
const Scene_Base::Observation& observation) {
|
|
layer.scene_observer.observe(observation);
|
|
}
|
|
};
|
|
|
|
Impl() = default;
|
|
explicit Impl(Scene_Observer observer)
|
|
: scene_observer(std::move(observer)) {}
|
|
std::uint64_t now_ns() const noexcept override {
|
|
return scene_observer.now_ns();
|
|
}
|
|
Scene_Observer scene_observer;
|
|
};
|
|
|
|
template <class... Args>
|
|
static Frame_Control make_frame_control(std::pmr::memory_resource& memory_resource, Args&&... args) {
|
|
if constexpr (std::constructible_from<Frame_Control, std::pmr::memory_resource&, Args&&...>) {
|
|
return Frame_Control(memory_resource, std::forward<Args>(args)...);
|
|
} else {
|
|
return Frame_Control(std::forward<Args>(args)...);
|
|
}
|
|
}
|
|
static Cache make_cache(std::pmr::memory_resource& memory_resource) {
|
|
if constexpr (std::constructible_from<Cache, std::pmr::memory_resource&>) {
|
|
return Cache(memory_resource);
|
|
} else {
|
|
return Cache();
|
|
}
|
|
}
|
|
static std::shared_ptr<Cache> make_cache_pointer(std::pmr::memory_resource& memory_resource) {
|
|
std::pmr::polymorphic_allocator<Cache> allocator(&memory_resource);
|
|
if constexpr (std::constructible_from<Cache, std::pmr::memory_resource&>) {
|
|
return std::allocate_shared<Cache>(allocator, memory_resource);
|
|
} else {
|
|
return std::allocate_shared<Cache>(allocator);
|
|
}
|
|
}
|
|
Cache final_color_cache_;
|
|
};
|