diff --git a/common/draw_panel_gal.cpp b/common/draw_panel_gal.cpp index f130cc89ed..9a602dd21d 100644 --- a/common/draw_panel_gal.cpp +++ b/common/draw_panel_gal.cpp @@ -62,8 +62,7 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin m_MouseCapturedLost( false ), m_parent( aParentWindow ), m_edaFrame( nullptr ), - m_lastRefresh( 0 ), - m_pendingRefresh( false ), + m_lastRepaint( 0 ), m_drawing( false ), m_drawingEnabled( false ), m_gal( nullptr ), @@ -79,8 +78,6 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin { m_PaintEventCounter = std::make_unique( "Draw panel paint events" ); - m_minRefreshPeriod = 13; // 77 FPS (minus render time) by default - SetLayoutDirection( wxLayout_LeftToRight ); m_edaFrame = dynamic_cast( m_parent ); @@ -191,13 +188,24 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) ) } -void EDA_DRAW_PANEL_GAL::DoRePaint() +bool EDA_DRAW_PANEL_GAL::DoRePaint() { if( !m_refreshMutex.try_lock() ) - return; + return false; std::lock_guard lock( m_refreshMutex, std::adopt_lock ); + if( !m_drawingEnabled ) + return false; + + if( !m_gal->IsInitialized() || !m_gal->IsVisible() ) + return false; + + if( m_drawing ) + return false; + + m_lastRepaint = wxGetLocalTimeMillis(); + // Repaint the canvas, and fix scrollbar cursors // Usually called by a OnPaint event, but because it does not use a wxPaintDC, // it can be called outside a wxPaintEvent. @@ -210,17 +218,6 @@ void EDA_DRAW_PANEL_GAL::DoRePaint() if( Pgm().GetCommonSettings()->m_Appearance.show_scrollbars ) m_viewControls->UpdateScrollbars(); - if( !m_drawingEnabled ) - return; - - if( !m_gal->IsInitialized() || !m_gal->IsVisible() ) - return; - - m_pendingRefresh = false; - - if( m_drawing ) - return; - SCOPED_SET_RESET drawing( m_drawing, true ); ( *m_PaintEventCounter )++; @@ -337,7 +334,7 @@ void EDA_DRAW_PANEL_GAL::DoRePaint() ); } - m_lastRefresh = wxGetLocalTimeMillis(); + return true; } @@ -382,28 +379,30 @@ void EDA_DRAW_PANEL_GAL::onSize( wxSizeEvent& aEvent ) void EDA_DRAW_PANEL_GAL::Refresh( bool aEraseBackground, const wxRect* aRect ) { wxLongLong t = wxGetLocalTimeMillis(); - wxLongLong delta = t - m_lastRefresh; + wxLongLong delta = t - m_lastRepaint; + + int minRefreshPeriod = 13; // 77 FPS limit when v-sync not available. + + if( m_gal && m_gal->IsInitialized() && m_gal->GetSwapInterval() != 0 ) + minRefreshPeriod = 3; // If it has been too long since the last frame (possible depending on platform timer latency), // just do a refresh. Otherwise, start the refresh timer if it hasn't already been started. // This ensures that we will render often enough but not too often. - if( delta >= m_minRefreshPeriod ) + if( delta >= minRefreshPeriod ) { - if( !m_pendingRefresh ) - ForceRefresh(); - - m_refreshTimer.Start( m_minRefreshPeriod, true ); + if( !DoRePaint() ) + m_refreshTimer.Start( minRefreshPeriod, true ); } else if( !m_refreshTimer.IsRunning() ) { - m_refreshTimer.Start( ( m_minRefreshPeriod - delta ).ToLong(), true ); + m_refreshTimer.Start( ( minRefreshPeriod - delta ).ToLong(), true ); } } void EDA_DRAW_PANEL_GAL::ForceRefresh() { - m_pendingRefresh = true; DoRePaint(); } @@ -426,7 +425,6 @@ void EDA_DRAW_PANEL_GAL::StopDrawing() m_refreshTimer.Stop(); m_drawingEnabled = false; Disconnect( wxEVT_PAINT, wxPaintEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), nullptr, this ); - m_pendingRefresh = false; } @@ -538,12 +536,6 @@ bool EDA_DRAW_PANEL_GAL::SwitchBackend( GAL_TYPE aGalType ) m_gal->SetGridVisibility( grid_visibility ); - if( m_gal->GetSwapInterval() != 0 ) - { - // In theory this could be 0 but then more CPU cycles will be wasted in SwapBuffers - m_minRefreshPeriod = 5; - } - // Make sure the cursor is set on the new canvas SetCurrentCursor( KICURSOR::ARROW ); @@ -613,7 +605,6 @@ void EDA_DRAW_PANEL_GAL::onRefreshTimer( wxTimerEvent& aEvent ) { if( m_gal && m_gal->IsInitialized() ) { - m_pendingRefresh = true; Connect( wxEVT_PAINT, wxPaintEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), nullptr, this ); m_drawingEnabled = true; diff --git a/include/class_draw_panel_gal.h b/include/class_draw_panel_gal.h index 9bdcf8ba12..cd848b8322 100644 --- a/include/class_draw_panel_gal.h +++ b/include/class_draw_panel_gal.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2013-2018 CERN - * Copyright (C) 2013-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2013-2023 KiCad Developers, see AUTHORS.txt for contributors. * * @author Tomasz Wlostowski * @author Maciej Suminski @@ -224,8 +224,10 @@ public: * Usually called by a OnPaint event. * * Because it does not use a wxPaintDC, it can be called outside a wxPaintEvent. + * + * @return true if the repaint attempt was successful. */ - void DoRePaint(); + bool DoRePaint(); /** * Create an overlay for rendering debug graphics. @@ -258,9 +260,7 @@ protected: wxWindow* m_parent; ///< Pointer to the parent window EDA_DRAW_FRAME* m_edaFrame; ///< Parent EDA_DRAW_FRAME (if available) - int m_minRefreshPeriod; ///< A minimum delay before another draw can start - wxLongLong m_lastRefresh; ///< Last timestamp when the panel was refreshed - bool m_pendingRefresh; ///< Is there a redraw event requested? + wxLongLong m_lastRepaint; ///< Timestamp of the last repaint start wxTimer m_refreshTimer; ///< Timer to prevent too-frequent refreshing std::mutex m_refreshMutex; ///< Blocks multiple calls to the draw