Files
Renderive/Core/plot/Latency_Eager_Refresh_Strategy.cpp
T
2026-08-01 20:09:45 +08:00

91 lines
2.9 KiB
C++

#include "Latency_Eager_Refresh_Strategy.h"
#include "../architecture/Render_Time.h"
namespace renderive {
struct Latency_Eager_Refresh_Strategy::Private {
std::atomic<double> max_render_fps{60.0};
Frame_Feedback_Controller feedback;
};
static constexpr double k_default_max_fps = 60.0;
Latency_Eager_Refresh_Strategy::Latency_Eager_Refresh_Strategy()
: d(std::make_unique<Private>()) {}
Latency_Eager_Refresh_Strategy::~Latency_Eager_Refresh_Strategy() = default;
double Latency_Eager_Refresh_Strategy::max_render_fps() const {
return d->max_render_fps.load(std::memory_order_acquire);
}
void Latency_Eager_Refresh_Strategy::set_max_render_fps(double fps) {
if (fps <= 0.0)
fps = k_default_max_fps;
d->max_render_fps.store(fps, std::memory_order_release);
}
Refresh_Control_Snapshot Latency_Eager_Refresh_Strategy::feedback_state() const {
return d->feedback.state();
}
Refresh_Action Latency_Eager_Refresh_Strategy::on_trigger(
Refresh_Trigger trigger,
const Refresh_Runtime_Snapshot& runtime,
const Frame_Lifecycle_Record* frame) {
d->feedback.set_max_render_fps(max_render_fps());
if (trigger == Refresh_Trigger::Started)
d->feedback.reset();
if (trigger == Refresh_Trigger::Input_Dirty)
d->feedback.on_input_changed(runtime.now_ns);
if (frame) {
switch (trigger) {
case Refresh_Trigger::Render_Finished:
d->feedback.on_render_completed(const_cast<Frame_Lifecycle_Record&>(*frame));
break;
case Refresh_Trigger::Frame_Returned:
if (frame->outcome == Frame_Outcome::Superseded)
d->feedback.on_frame_superseded(const_cast<Frame_Lifecycle_Record&>(*frame));
else
d->feedback.on_frame_presented(const_cast<Frame_Lifecycle_Record&>(*frame));
break;
default:
break;
}
}
Refresh_Action action;
if (!runtime.enabled || runtime.destroying || trigger == Refresh_Trigger::Paused)
return action;
if (runtime.middle_has_new_frame && !runtime.paint_active)
action.request_paint = true;
if (!runtime.dirty || runtime.render_job_active)
return action;
Refresh_Control_Snapshot control = d->feedback.state();
switch (control.source) {
case Refresh_Limit_Source::Paint:
if (!runtime.middle_has_new_frame)
action.try_render = true;
break;
case Refresh_Limit_Source::User: {
std::uint64_t next_ns = d->feedback.next_render_time_ns();
if (next_ns && !d->feedback.rate_limit_ready(runtime.now_ns))
action.render_deadline_ns = next_ns;
else
action.try_render = true;
break;
}
case Refresh_Limit_Source::Render:
case Refresh_Limit_Source::Unknown:
action.try_render = true;
break;
}
return action;
}
} // namespace renderive