diff --git a/ClockReceiver/VSyncPredictor.hpp b/ClockReceiver/VSyncPredictor.hpp index 229a8d636..f34ed55c5 100644 --- a/ClockReceiver/VSyncPredictor.hpp +++ b/ClockReceiver/VSyncPredictor.hpp @@ -63,6 +63,13 @@ class VSyncPredictor { frame_duration_ = Nanos(1'000'000'000.0f / rate); } + /*! + @returns The time this class currently believes a whole frame occupies. + */ + Time::Nanos frame_duration() { + return frame_duration_; + } + /*! Adds a record of how much jitter was experienced in scheduling; these values will be factored into the @c suggested_draw_time if supplied. @@ -87,15 +94,13 @@ class VSyncPredictor { (if those figures are being supplied). */ Nanos suggested_draw_time() { - const auto mean = redraw_period_.mean() - timer_jitter_.mean() - vsync_jitter_.mean(); + const auto mean = redraw_period_.mean() + timer_jitter_.mean() + vsync_jitter_.mean(); const auto variance = redraw_period_.variance() + timer_jitter_.variance() + vsync_jitter_.variance(); // Permit three standard deviations from the mean, to cover 99.9% of cases. - const auto period = mean - Nanos(3.0f * sqrt(float(variance))); + const auto period = mean + Nanos(3.0f * sqrt(float(variance))); - assert(abs(period) < 10'000'000'000); - - return last_vsync_ + period; + return last_vsync_ + frame_duration_ - period; } private: @@ -109,7 +114,6 @@ class VSyncPredictor { } void post(Time::Nanos value) { - assert(abs(value) < 10'000'000'000); // 10 seconds is a very liberal maximum. sum_ -= history_[write_pointer_]; sum_ += value; history_[write_pointer_] = value; diff --git a/OSBindings/Qt/scantargetwidget.cpp b/OSBindings/Qt/scantargetwidget.cpp index 99072b486..3fbbc7c53 100644 --- a/OSBindings/Qt/scantargetwidget.cpp +++ b/OSBindings/Qt/scantargetwidget.cpp @@ -86,7 +86,7 @@ void ScanTargetWidget::vsync() { const auto time_now = Time::nanos_now(); requestedRedrawTime = vsyncPredictor.suggested_draw_time(); const auto delay_time = (requestedRedrawTime - time_now) / 1'000'000; - if(delay_time > 0) { + if(delay_time > 0 && delay_time < vsyncPredictor.frame_duration()) { QTimer::singleShot(delay_time, this, SLOT(repaint())); } else { requestedRedrawTime = 0;