Files
Renderive/YSGraphic_Core/architecture/Render_Data.h
T
2026-07-28 10:54:38 +08:00

317 lines
11 KiB
C++

#pragma once
#include <QImage>
#include <QRegion>
#include <array>
#include <atomic>
#include <cstdint>
#include "Render_Config.h"
#include "global.h"
class QEvent;
class QKeyEvent;
class QMouseEvent;
class QPainter;
class QPointF;
class QResizeEvent;
class QWheelEvent;
namespace YSG {
struct Render_Data;
struct Renderable;
struct Input_Data {
virtual ~Input_Data() = default;
virtual void clear() {
}
virtual std::uint64_t pending_count() const {
return 0;
}
virtual std::uint64_t dropped_count() const {
return 0;
}
virtual std::uint64_t pushed_count() const {
return 0;
}
};
struct Render_State {
virtual ~Render_State() = default;
std::uint64_t version = 0;
Render_Data* dPtr{};
SRC src();
};
struct Input_Buffer_Slot {
Input_Data* data{};
std::uint64_t version = 0;
bool pending = false;
};
struct Pixel_Buffer_Slot {
std::atomic<std::uint64_t> version{0};
QImage image;
QRegion dirtyRegion;
};
struct Pixel_Buffer_Lease {
Pixel_Buffer_Slot* buffer{};
Triple_Buffer_Lease lease{};
explicit operator bool() const {
return buffer && lease;
}
};
struct Render_Data {
Render_Data() {
mStateControl.set_stats(&mStateBufferStats);
mInputControl.set_stats(&mInputBufferStats);
mPixelControl.set_stats(&mPixelBufferStats);
}
Renderable* qPtr{};
bool mRenderStart = false;
Triple_Role_Buffer_Control mStateControl;
Triple_Buffer_Stats mStateBufferStats;
std::array<Render_State*, 3> mStateBuffers{};
Triple_Role_Buffer_Control mInputControl;
Triple_Buffer_Stats mInputBufferStats;
std::array<Input_Buffer_Slot, 3> mInputBuffers{};
std::uint64_t mInputVersion = 0;
std::atomic<Plot_Buffer_Acquire_Mode> mBufferAcquireMode{Plot_Buffer_Acquire_Mode::Wait};
std::atomic<RenderAble_Render_Schedule_Mode> mRenderScheduleMode{RenderAble_Render_Schedule_Mode::Inherit};
std::atomic<double> mRenderScheduleMaxFps{0.0};
std::atomic<std::uint64_t> mNextRenderSubmitNs{0};
Triple_Role_Buffer_Control mPixelControl;
Triple_Buffer_Stats mPixelBufferStats;
std::array<Pixel_Buffer_Slot, 3> mPixelBuffers{};
std::atomic_bool mIndependentPixelCache{false};
std::atomic_bool mIndependentRenderQueued{false};
std::atomic<std::uint64_t> mPixelEditVersion{1};
std::uint64_t mPixelRenderVersion = 0;
Render_State* state(std::uint8_t role) const {
return state_by_index(mStateControl.read_view()[role]);
}
Render_State* state(SRC src) const {
return state(static_cast<std::uint8_t>(src));
}
Render_State* state_by_index(std::uint8_t index) const {
return mStateBuffers[index];
}
Plot_Buffer_Acquire_Mode buffer_acquire_mode() const {
return mBufferAcquireMode.load(std::memory_order_acquire);
}
void set_buffer_acquire_mode(Plot_Buffer_Acquire_Mode mode) {
mBufferAcquireMode.store(mode, std::memory_order_release);
}
RenderAble_Render_Schedule_Mode render_schedule_mode() const {
return mRenderScheduleMode.load(std::memory_order_acquire);
}
void set_render_schedule_mode(RenderAble_Render_Schedule_Mode mode) {
mRenderScheduleMode.store(mode, std::memory_order_release);
}
double render_schedule_max_fps() const {
return mRenderScheduleMaxFps.load(std::memory_order_acquire);
}
void set_render_schedule_max_fps(double fps) {
mRenderScheduleMaxFps.store(fps, std::memory_order_release);
}
Triple_Buffer_Lease mark_state_role(std::uint8_t role) {
if (buffer_acquire_mode() == Plot_Buffer_Acquire_Mode::Wait) {
return mStateControl.wait_mark_use_role(role);
}
auto record = mStateControl.try_mark_use_role(role);
if (record.result != Triple_Buffer_Result::Success) {
return {};
}
return record.lease;
}
void unmark_state(Triple_Buffer_Lease lease) {
mStateControl.unmark_use(lease);
}
void clear_state_buffers() {
for (Render_State*& state : mStateBuffers) {
delete state;
state = nullptr;
}
mStateControl.reset();
}
Input_Data* input_data(std::uint8_t role) const {
return input_slot(role).data;
}
Input_Data* input_data_by_index(std::uint8_t index) const {
return mInputBuffers[index].data;
}
Input_Buffer_Slot& input_slot(std::uint8_t role) {
return input_slot_by_index(mInputControl.read_view()[role]);
}
const Input_Buffer_Slot& input_slot(std::uint8_t role) const {
return input_slot_by_index(mInputControl.read_view()[role]);
}
Input_Buffer_Slot& input_slot_by_index(std::uint8_t index) {
return mInputBuffers[index];
}
const Input_Buffer_Slot& input_slot_by_index(std::uint8_t index) const {
return mInputBuffers[index];
}
bool has_pending_state() const {
auto view = mStateControl.read_view();
return buffer_version_newer(mStateBuffers[view[State_Edit]]->version, mStateBuffers[view[State_Render]]->version);
}
bool has_pending_input() const {
auto view = mInputControl.read_view();
const Input_Buffer_Slot& edit = mInputBuffers[view[Input_Edit]];
const Input_Buffer_Slot& ready = mInputBuffers[view[Input_Ready]];
const Input_Buffer_Slot& render = mInputBuffers[view[Input_Render]];
return (edit.pending && buffer_version_newer(edit.version, render.version)) || (ready.pending && buffer_version_newer(ready.version, render.version));
}
bool has_pending_render_data() const {
return has_pending_state() || has_pending_input();
}
void mark_input_dirty(Triple_Buffer_Lease lease, bool notifyRender = true);
void clear_input_role(std::uint8_t role) {
Input_Buffer_Slot& slot = input_slot(role);
slot.data->clear();
slot.pending = false;
}
void clear_render_input() {
clear_input_role(Input_Render);
}
void clear_input_buffers() {
for (Input_Buffer_Slot& slot : mInputBuffers) {
delete slot.data;
slot.data = nullptr;
slot.version = 0;
slot.pending = false;
}
mInputVersion = 0;
mInputControl.reset();
}
bool independent_pixel_cache() const {
return mIndependentPixelCache.load(std::memory_order_acquire);
}
void set_independent_pixel_cache(bool enabled) {
mIndependentPixelCache.store(enabled, std::memory_order_release);
}
Pixel_Buffer_Slot* pixel_by_index(std::uint8_t index) {
return &mPixelBuffers[index];
}
Pixel_Buffer_Lease wait_render_pixel() {
auto lease = mPixelControl.wait_mark_use_role(Color_Render);
return {pixel_by_index(lease.index), lease};
}
Pixel_Buffer_Lease try_front_pixel() {
auto record = mPixelControl.try_mark_use_role(Color_Front);
if (record.result != Triple_Buffer_Result::Success)
return {};
return {pixel_by_index(record.lease.index), record.lease};
}
void unmark_pixel(Pixel_Buffer_Lease lease) {
mPixelControl.unmark_use(lease.lease);
}
bool has_new_pixel_state() const {
return buffer_version_newer(mPixelEditVersion.load(std::memory_order_acquire), mPixelRenderVersion);
}
void mark_pixel_dirty() {
mPixelEditVersion.fetch_add(1, std::memory_order_release);
}
QRegion publish_render_pixel() {
mPixelControl.wait_swap_role(Color_Ready, Color_Render, [this](const Triple_Buffer_View& view) {
auto render = pixel_by_index(view[Color_Render]);
auto ready = pixel_by_index(view[Color_Ready]);
return buffer_version_newer(render->version.load(std::memory_order_acquire), ready->version.load(std::memory_order_acquire));
});
auto view = mPixelControl.read_view();
auto ready = pixel_by_index(view[Color_Ready]);
auto front = pixel_by_index(view[Color_Front]);
if (buffer_version_newer(ready->version.load(std::memory_order_acquire), front->version.load(std::memory_order_acquire)))
return ready->dirtyRegion;
return {};
}
Pixel_Buffer_Lease consume_ready_pixel(Triple_Buffer_Mode mode) {
auto canSwap = [this](const Triple_Buffer_View& view) {
auto ready = pixel_by_index(view[Color_Ready]);
auto front = pixel_by_index(view[Color_Front]);
return buffer_version_newer(ready->version.load(std::memory_order_acquire), front->version.load(std::memory_order_acquire));
};
if (mode == Triple_Buffer_Mode::Wait) {
mPixelControl.wait_swap_role(Color_Front, Color_Ready, canSwap);
}
else {
mPixelControl.try_swap_role(Color_Front, Color_Ready, canSwap);
}
return try_front_pixel();
}
public:
/// 同步 State/Input 的 ready 角色到 render 角色。
virtual void sync_state_pipeline() = 0;
/// 返回 render 角色 State。
virtual Render_State* render_state() = 0;
/// 返回 ready 角色 State。
virtual Render_State* ready_state() = 0;
/// 返回 edit 角色 State。
virtual Render_State* edit_state() = 0;
/// 返回 render 角色 Input。
virtual Input_Data* render_input_data() = 0;
/// 返回 edit 角色 Input。
virtual Input_Data* edit_input_data() = 0;
virtual ~Render_Data() {
clear_state_buffers();
clear_input_buffers();
}
/// 绘制当前已准备好的数据。
virtual void draw(QPainter* painter) {
}
/// 准备当前帧数据,默认只同步三缓冲管线。
virtual void prepare_data() {
sync_state_pipeline();
}
/// 判断指定坐标是否命中对象。
virtual bool select_test(const QPointF& pos) {
return false;
}
virtual void plot_event(QEvent* event) {
}
virtual void mousePressEvent(QMouseEvent* event) {
}
virtual void mouseMoveEvent(QMouseEvent* event) {
}
virtual void mouseReleaseEvent(QMouseEvent* event) {
}
virtual void set_hover_state(const QPoint& pos, bool active) {
}
virtual void keyPressEvent(QKeyEvent* event) {
}
virtual void keyReleaseEvent(QKeyEvent* event) {
}
virtual void first_resize_event(QResizeEvent* event) {
}
virtual void resizeEvent(QResizeEvent* event) {
}
virtual void wheelEvent(QWheelEvent* event) {
}
};
struct Base_Render_Data : Render_Data {
Render_State* render_state() override {
return nullptr;
}
Render_State* ready_state() override {
return nullptr;
}
Render_State* edit_state() override {
return nullptr;
}
Input_Data* render_input_data() override {
return nullptr;
}
Input_Data* edit_input_data() override {
return nullptr;
}
void sync_state_pipeline() override {
}
};
class Plot;
struct LIB_DECL Render_Edit_Guard {
Render_Edit_Guard(Render_Data* data, Triple_Buffer_Lease lease);
~Render_Edit_Guard();
Render_Data* mData{};
Triple_Buffer_Lease mLease{};
};
struct LIB_DECL Render_Input_Guard {
Render_Input_Guard(Render_Data* data, Triple_Buffer_Lease lease);
~Render_Input_Guard();
Render_Data* mData{};
Triple_Buffer_Lease mLease{};
};
} // namespace YSG