#pragma once #include #include #include #include #include #include #include "Render_Config.h" #include "Plot_Render_Context.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 capacity_dropped_count() const { return 0; } virtual std::uint64_t rebuild_dropped_count() const { return 0; } virtual std::uint64_t consumer_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 Render_Data { Render_Data() { mStateControl.set_stats(&mStateBufferStats); mInputControl.set_stats(&mInputBufferStats); } Renderable* qPtr{}; bool mRenderStart = false; Triple_Role_Buffer_Control mStateControl; Triple_Buffer_Stats mStateBufferStats; std::array mStateBuffers{}; Triple_Role_Buffer_Control mInputControl; Triple_Buffer_Stats mInputBufferStats; std::array mInputBuffers{}; std::uint64_t mInputVersion = 0; std::atomic mBufferAcquireMode{Plot_Buffer_Acquire_Mode::Wait}; std::atomic mRenderScheduleMode{RenderAble_Render_Schedule_Mode::Inherit}; std::atomic mRenderScheduleMaxFps{0.0}; std::atomic mNextRenderSubmitNs{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(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(); } 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, const Plot_Render_Snapshot& snapshot) { } /// 准备当前帧数据,默认只同步三缓冲管线。 virtual void prepare_data(const Plot_Render_Snapshot& snapshot) { sync_state_pipeline(); } virtual QRect pixel_bounds(const QSize& plotSize) { return QRect(QPoint(0, 0), plotSize); } /// 判断指定坐标是否命中对象。 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 Abs_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