Files
Renderive/Core/flow/Present_Surface_Lease.h
T
2026-08-02 14:57:24 +08:00

91 lines
3.3 KiB
C++

#pragma once
#include "../render/Image_View.h"
#include "../render/Render_Output.h"
#include <cstddef>
#include <cstdint>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
namespace renderive {
struct Present_Surface_Lease_Access;
class Present_Surface_Lease {
public:
Present_Surface_Lease();
Present_Surface_Lease(Present_Surface_Lease&& other) noexcept;
Present_Surface_Lease& operator=(Present_Surface_Lease&& other) noexcept;
~Present_Surface_Lease();
[[nodiscard]] explicit operator bool() const;
[[nodiscard]] bool new_frame() const;
[[nodiscard]] bool request_was_pending() const;
[[nodiscard]] Image_View image() const;
private:
friend struct Present_Surface_Lease_Access;
static constexpr std::size_t Storage_Size = 96;
static constexpr std::size_t Storage_Align = alignof(std::max_align_t);
using Storage = std::aligned_storage_t<Storage_Size, Storage_Align>;
using Output_Fn = Render_Output* (*)(const void*);
using Destroy_Fn = void (*)(void*);
using Move_Fn = void (*)(void*, void*);
template <typename Handle, typename... Args>
static Present_Surface_Lease from_handle(bool is_new_frame, bool update_was_pending, Args&&... args) {
static_assert(sizeof(Handle) <= Storage_Size, "Present surface handle exceeds inline lease storage");
static_assert(alignof(Handle) <= Storage_Align, "Present surface handle exceeds inline lease alignment");
Present_Surface_Lease lease;
std::construct_at(reinterpret_cast<Handle*>(&lease.storage_), std::forward<Args>(args)...);
lease.output_ = [](const void* storage) -> Render_Output* {
return reinterpret_cast<const Handle*>(storage)->output();
};
lease.destroy_ = [](void* storage) {
std::destroy_at(reinterpret_cast<Handle*>(storage));
};
lease.move_ = [](void* destination, void* source) {
std::construct_at(reinterpret_cast<Handle*>(destination), std::move(*reinterpret_cast<Handle*>(source)));
std::destroy_at(reinterpret_cast<Handle*>(source));
};
lease.is_new_frame = is_new_frame;
lease.update_was_pending = update_was_pending;
return lease;
}
static Present_Surface_Lease empty(bool is_new_frame, bool update_was_pending);
[[nodiscard]] Render_Output* output() const;
void reset();
void move_from(Present_Surface_Lease&& other) noexcept;
Storage storage_{};
Output_Fn output_{};
Destroy_Fn destroy_{};
Move_Fn move_{};
bool is_new_frame{};
bool update_was_pending{};
};
struct Present_Surface_Lease_Access {
template <typename Handle, typename... Args>
static Present_Surface_Lease from_handle(bool is_new_frame, bool update_was_pending, Args&&... args) {
return Present_Surface_Lease::from_handle<Handle>(is_new_frame, update_was_pending, std::forward<Args>(args)...);
}
static Present_Surface_Lease empty(bool is_new_frame, bool update_was_pending) {
return Present_Surface_Lease::empty(is_new_frame, update_was_pending);
}
static Render_Output* output(const Present_Surface_Lease& lease) {
return lease.output();
}
static void reset(Present_Surface_Lease& lease) {
lease.reset();
}
};
} // namespace renderive