1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-30 04:50:08 +00:00
CLK/Outputs/DisplayMetrics.cpp

89 lines
2.4 KiB
C++

//
// DisplayMetrics.cpp
// Clock Signal
//
// Created by Thomas Harte on 04/03/2019.
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#include "DisplayMetrics.hpp"
#include <numeric>
using namespace Outputs::Display;
// MARK: Frame size estimation.
void Metrics::announce_event(ScanTarget::Event event) {
switch(event) {
case ScanTarget::Event::EndHorizontalRetrace:
++lines_this_frame_;
break;
case ScanTarget::Event::BeginVerticalRetrace:
add_line_total(lines_this_frame_);
break;
case ScanTarget::Event::EndVerticalRetrace:
lines_this_frame_ = 0;
break;
default: break;
}
}
void Metrics::add_line_total(int total) {
line_total_history_[line_total_history_pointer_] = total;
line_total_history_pointer_ = (line_total_history_pointer_ + 1) % line_total_history_.size();
}
float Metrics::visible_lines_per_frame_estimate() {
// Just average the number of records contained in line_total_history_ to provide this estimate;
// that array should be an even number, to allow for potential interlaced sources.
return float(std::accumulate(line_total_history_.begin(), line_total_history_.end(), 0)) / float(line_total_history_.size());
}
int Metrics::current_line() {
return lines_this_frame_;
}
// MARK: GPU processing speed decisions.
void Metrics::announce_did_resize() {
frames_missed_ = frames_hit_ = 0;
}
void Metrics::announce_draw_status(size_t lines, std::chrono::high_resolution_clock::duration duration, bool complete) {
if(!complete) {
++frames_missed_;
} else {
++frames_hit_;
}
// Don't allow the record of history to extend too far into the past.
if(frames_hit_ + frames_missed_ > 200) {
// Subtract from whichever wasn't just incremented, to ensure the
// most recent information is more important than the historic stuff.
if(!complete) {
--frames_hit_;
} else {
--frames_missed_;
}
// Rebalance if either thing has gone negative.
if(frames_hit_ < 0) {
frames_missed_ += frames_hit_;
frames_hit_ = 0;
}
if(frames_missed_ < 0) {
frames_hit_ += frames_missed_;
frames_missed_ = 0;
}
}
}
bool Metrics::should_lower_resolution() {
// If less than 100 frames are on record, return no opinion; otherwise
// suggest a lower resolution if more than 10 frames in the last 100-200
// took too long to produce.
if(frames_hit_ + frames_missed_ < 100) return false;
return frames_missed_ > 10;
}