Dynamic adjustment of the terminal refresh rate between 5 and 60 Hz

This commit is contained in:
Markus Gans 2021-03-15 01:37:25 +01:00
parent d4f629f183
commit e6dfd73e7a
6 changed files with 73 additions and 9 deletions

View File

@ -1,4 +1,8 @@
2021-02-09 Markus Gans <guru.mail@muenster.de> 2021-03-15 Markus Gans <guru.mail@muenster.de>
* Dynamic adjustment of the terminal refresh rate between
5 and 60 Hz
2021-03-09 Markus Gans <guru.mail@muenster.de>
* Implementation of an own padding print method for sending * Implementation of an own padding print method for sending
control codes to the terminal control codes to the terminal

View File

@ -149,13 +149,11 @@ bool FKeyboard::isKeyPressed (uInt64 blocking_time)
tv.tv_sec = tv.tv_usec = 0; // Non-blocking input tv.tv_sec = tv.tv_usec = 0; // Non-blocking input
if ( blocking_time > 0 if ( blocking_time > 0
&& non_blocking_input_support && non_blocking_input_support
&& select(stdin_no + 1, &ifds, nullptr, nullptr, &tv) > 0 && select(stdin_no + 1, &ifds, nullptr, nullptr, &tv) > 0
&& FD_ISSET(stdin_no, &ifds) ) && FD_ISSET(stdin_no, &ifds) )
{ {
has_pending_input = true; return (has_pending_input = true);
FD_CLR (stdin_no, &ifds);
tv.tv_sec = 0;
} }
if ( isKeypressTimeout() || ! non_blocking_input_support ) if ( isKeypressTimeout() || ! non_blocking_input_support )

View File

@ -438,7 +438,6 @@ std::string FTermcap::encodeParams ( const std::string& cap
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FTermcap::delay_output (int ms, const defaultPutChar& outc) void FTermcap::delay_output (int ms, const defaultPutChar& outc)
{ {
if ( no_padding_char ) if ( no_padding_char )
{ {
std::this_thread::sleep_for(std::chrono::milliseconds(ms)); std::this_thread::sleep_for(std::chrono::milliseconds(ms));

View File

@ -60,7 +60,9 @@ bool FVTerm::combined_char_support{false};
bool FVTerm::no_terminal_updates{false}; bool FVTerm::no_terminal_updates{false};
bool FVTerm::cursor_hideable{false}; bool FVTerm::cursor_hideable{false};
bool FVTerm::force_terminal_update{false}; bool FVTerm::force_terminal_update{false};
uInt64 FVTerm::flush_wait{16667}; // 16.6 ms (60 Hz) uInt64 FVTerm::flush_wait{MIN_FLUSH_WAIT};
uInt64 FVTerm::flush_average{MIN_FLUSH_WAIT};
uInt64 FVTerm::flush_median{MIN_FLUSH_WAIT};
uInt64 FVTerm::term_size_check_timeout{500000}; // 500 ms uInt64 FVTerm::term_size_check_timeout{500000}; // 500 ms
uInt FVTerm::erase_char_length{}; uInt FVTerm::erase_char_length{};
uInt FVTerm::repeat_char_length{}; uInt FVTerm::repeat_char_length{};
@ -573,6 +575,8 @@ void FVTerm::flush() const
{ {
// Flush the output buffer // Flush the output buffer
flushTimeAdjustment();
if ( ! output_buffer || output_buffer->empty() if ( ! output_buffer || output_buffer->empty()
|| ! (isFlushTimeout() || force_terminal_update) ) || ! (isFlushTimeout() || force_terminal_update) )
return; return;
@ -2888,6 +2892,52 @@ inline bool FVTerm::isTermSizeChanged() const
return false; return false;
} }
//----------------------------------------------------------------------
inline void FVTerm::flushTimeAdjustment() const
{
timeval now;
FObject::getCurrentTime(&now);
timeval diff = now - time_last_flush;
if ( diff.tv_sec > 0 || diff.tv_usec > 400000 )
{
flush_wait = MIN_FLUSH_WAIT; // Reset to minimum values after 400 ms
flush_average = MIN_FLUSH_WAIT;
flush_median = MIN_FLUSH_WAIT;
}
else
{
uInt64 usec = diff.tv_usec;
if ( usec < MIN_FLUSH_WAIT )
usec = MIN_FLUSH_WAIT;
else if ( usec > MAX_FLUSH_WAIT )
usec = MAX_FLUSH_WAIT;
if ( usec >= flush_average )
flush_average += (usec - flush_average) / 10;
else
{
uInt64 delta = (flush_average - usec) / 10;
if ( flush_average >= delta ) // Avoid uInt64 underflow
flush_average -= delta;
}
if ( usec >= flush_median )
flush_median += flush_average / 5;
else
{
uInt64 delta = flush_average / 5;
if ( flush_median >= delta ) // Avoid uInt64 underflow
flush_median -= delta;
}
flush_wait = flush_median;
}
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FVTerm::isFlushTimeout() inline bool FVTerm::isFlushTimeout()
{ {

View File

@ -345,6 +345,9 @@ class FVTerm
// Constants // Constants
// Buffer limit for character output on the terminal // Buffer limit for character output on the terminal
static constexpr std::size_t TERMINAL_OUTPUT_BUFFER_LIMIT = 1024; static constexpr std::size_t TERMINAL_OUTPUT_BUFFER_LIMIT = 1024;
// Upper and lower flush limit
static constexpr uInt64 MIN_FLUSH_WAIT = 16667; // 16.6 ms = 60 Hz
static constexpr uInt64 MAX_FLUSH_WAIT = 200000; // 200.0 ms = 5 Hz
// Methods // Methods
void resetTextAreaToDefault ( const FTermArea* void resetTextAreaToDefault ( const FTermArea*
@ -412,6 +415,7 @@ class FVTerm
bool updateTerminalCursor() const; bool updateTerminalCursor() const;
bool isInsideTerminal (const FPoint&) const; bool isInsideTerminal (const FPoint&) const;
bool isTermSizeChanged() const; bool isTermSizeChanged() const;
void flushTimeAdjustment() const;
static bool isFlushTimeout(); static bool isFlushTimeout();
static bool isTermSizeCheckTimeout(); static bool isTermSizeCheckTimeout();
static bool hasPendingUpdates (const FTermArea*); static bool hasPendingUpdates (const FTermArea*);
@ -451,6 +455,8 @@ class FVTerm
static bool no_terminal_updates; static bool no_terminal_updates;
static bool force_terminal_update; static bool force_terminal_update;
static uInt64 flush_wait; static uInt64 flush_wait;
static uInt64 flush_average;
static uInt64 flush_median;
static uInt64 term_size_check_timeout; static uInt64 term_size_check_timeout;
static uInt erase_char_length; static uInt erase_char_length;
static uInt repeat_char_length; static uInt repeat_char_length;

View File

@ -276,6 +276,13 @@ void FTermcapTest::paddingPrintTest()
CPPUNIT_ASSERT ( ! output.empty() ); CPPUNIT_ASSERT ( ! output.empty() );
CPPUNIT_ASSERT ( output == "12$3$<4567" ); CPPUNIT_ASSERT ( output == "12$3$<4567" );
// Without a digit
output.clear();
status = tcap.paddingPrint ("12$3$<x>4567", 1, FTermcapTest::putchar_test);
CPPUNIT_ASSERT ( status == finalcut::FTermcap::Status::OK );
CPPUNIT_ASSERT ( ! output.empty() );
CPPUNIT_ASSERT ( output == "12$3$<x>4567" );
// With 2 ms print delay // With 2 ms print delay
output.clear(); output.clear();
auto start = high_resolution_clock::now(); auto start = high_resolution_clock::now();