diff --git a/common/draw_panel_gal.cpp b/common/draw_panel_gal.cpp index c98cc64125..4037ba1f73 100644 --- a/common/draw_panel_gal.cpp +++ b/common/draw_panel_gal.cpp @@ -121,7 +121,7 @@ EDA_DRAW_PANEL_GAL::~EDA_DRAW_PANEL_GAL() { StopDrawing(); - assert( !m_drawing ); + wxASSERT( !m_drawing ); delete m_viewControls; delete m_view; @@ -163,10 +163,10 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) ) m_viewControls->UpdateScrollbars(); - m_view->UpdateItems(); - try { + m_view->UpdateItems(); + m_gal->BeginDrawing(); m_gal->SetClearColor( settings->GetBackgroundColor() ); m_gal->SetCursorColor( settings->GetLayerColor( LAYER_CURSOR ) ); @@ -188,13 +188,17 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) ) } catch( std::runtime_error& err ) { - assert( GetBackend() != GAL_TYPE_CAIRO ); - - // Cairo is supposed to be the safe backend, there is not a single "throw" in its code - SwitchBackend( GAL_TYPE_CAIRO ); + constexpr auto GAL_FALLBACK = GAL_TYPE_CAIRO; if( m_edaFrame ) - m_edaFrame->UseGalCanvas( true ); + { + bool use_gal = m_edaFrame->SwitchCanvas( GAL_FALLBACK ); + m_edaFrame->UseGalCanvas( use_gal ); + } + else + { + SwitchBackend( GAL_TYPE_CAIRO ); + } DisplayError( m_parent, wxString( err.what() ) ); } @@ -363,6 +367,7 @@ bool EDA_DRAW_PANEL_GAL::SwitchBackend( GAL_TYPE aGalType ) } catch( std::runtime_error& err ) { + // Create a dummy GAL new_gal = new KIGFX::GAL( m_options ); aGalType = GAL_TYPE_NONE; DisplayError( m_parent, wxString( err.what() ) ); diff --git a/include/draw_frame.h b/include/draw_frame.h index 6d925eb52d..c3e13d9d60 100644 --- a/include/draw_frame.h +++ b/include/draw_frame.h @@ -337,6 +337,12 @@ public: bool ShowPageLimits() const { return m_showPageLimits; } void SetShowPageLimits( bool aShow ) { m_showPageLimits = aShow; } + virtual bool SwitchCanvas( EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType ) + { + wxFAIL_MSG( "SwitchCanvas not implemented" ); + return false; + } + EDA_DRAW_PANEL* GetCanvas() { return m_canvas; } virtual wxString GetScreenDesc() const; diff --git a/include/wxBasePcbFrame.h b/include/wxBasePcbFrame.h index 57d63cbe58..493bfe635a 100644 --- a/include/wxBasePcbFrame.h +++ b/include/wxBasePcbFrame.h @@ -40,7 +40,6 @@ #include // EDA_DRAW_MODE_T #include #include - #include #include @@ -648,6 +647,8 @@ public: void OnTogglePolarCoords( wxCommandEvent& aEvent ); void OnTogglePadDrawMode( wxCommandEvent& aEvent ); + virtual void OnSwitchCanvas( wxCommandEvent& aEvent ); + // User interface update event handlers. void OnUpdateCoordType( wxUpdateUIEvent& aEvent ); void OnUpdatePadDrawMode( wxUpdateUIEvent& aEvent ); @@ -688,7 +689,7 @@ public: /** * switches currently used canvas (default / Cairo / OpenGL). */ - virtual void SwitchCanvas( wxCommandEvent& aEvent ); + bool SwitchCanvas( EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType ) override; /** * Update UI called when switches currently used canvas (default / Cairo / OpenGL). diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp index 93088c7bd4..b6b8a8adf3 100644 --- a/pcbnew/basepcbframe.cpp +++ b/pcbnew/basepcbframe.cpp @@ -480,6 +480,25 @@ void PCB_BASE_FRAME::OnTogglePadDrawMode( wxCommandEvent& aEvent ) } +void PCB_BASE_FRAME::OnSwitchCanvas( wxCommandEvent& aEvent ) +{ + switch( aEvent.GetId() ) + { + case ID_MENU_CANVAS_LEGACY: + SwitchCanvas( EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE ); + break; + + case ID_MENU_CANVAS_CAIRO: + SwitchCanvas( EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO ); + break; + + case ID_MENU_CANVAS_OPENGL: + SwitchCanvas( EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL ); + break; + } +} + + void PCB_BASE_FRAME::OnUpdateCoordType( wxUpdateUIEvent& aEvent ) { auto displ_opts = (PCB_DISPLAY_OPTIONS*)GetDisplayOptions(); @@ -949,38 +968,6 @@ void PCB_BASE_FRAME::SetPrevGrid() } -void PCB_BASE_FRAME::SwitchCanvas( wxCommandEvent& aEvent ) -{ - bool use_gal = false; - EDA_DRAW_PANEL_GAL::GAL_TYPE canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE; - - switch( aEvent.GetId() ) - { - case ID_MENU_CANVAS_LEGACY: - break; - - case ID_MENU_CANVAS_CAIRO: - use_gal = GetGalCanvas()->SwitchBackend( EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO ); - - if( use_gal ) - canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO; - break; - - case ID_MENU_CANVAS_OPENGL: - use_gal = GetGalCanvas()->SwitchBackend( EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL ); - - if( use_gal ) - canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL; - break; - } - - UseGalCanvas( use_gal ); - - m_canvasType = canvasType; - m_canvasTypeDirty = true; -} - - void PCB_BASE_FRAME::UseGalCanvas( bool aEnable ) { EDA_DRAW_FRAME::UseGalCanvas( aEnable ); @@ -1019,6 +1006,18 @@ void PCB_BASE_FRAME::UseGalCanvas( bool aEnable ) } +bool PCB_BASE_FRAME::SwitchCanvas( EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType ) +{ + bool use_gal = GetGalCanvas()->SwitchBackend( aCanvasType ); + use_gal &= aCanvasType != EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE; + UseGalCanvas( use_gal ); + m_canvasType = use_gal ? aCanvasType : EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE; + m_canvasTypeDirty = true; + + return use_gal; +} + + void PCB_BASE_FRAME::OnUpdateSwitchCanvas( wxUpdateUIEvent& aEvent ) { wxMenuBar* menuBar = GetMenuBar(); diff --git a/pcbnew/moduleframe.cpp b/pcbnew/moduleframe.cpp index 8e38861123..0ed3507a29 100644 --- a/pcbnew/moduleframe.cpp +++ b/pcbnew/moduleframe.cpp @@ -181,9 +181,9 @@ BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME ) EVT_MENU( ID_MENU_PCB_SHOW_3D_FRAME, FOOTPRINT_EDIT_FRAME::Show3D_Frame ) // Switching canvases - EVT_MENU( ID_MENU_CANVAS_LEGACY, PCB_BASE_FRAME::SwitchCanvas ) - EVT_MENU( ID_MENU_CANVAS_CAIRO, PCB_BASE_FRAME::SwitchCanvas ) - EVT_MENU( ID_MENU_CANVAS_OPENGL, PCB_BASE_FRAME::SwitchCanvas ) + EVT_MENU( ID_MENU_CANVAS_LEGACY, PCB_BASE_FRAME::OnSwitchCanvas ) + EVT_MENU( ID_MENU_CANVAS_CAIRO, PCB_BASE_FRAME::OnSwitchCanvas ) + EVT_MENU( ID_MENU_CANVAS_OPENGL, PCB_BASE_FRAME::OnSwitchCanvas ) // UI update events. EVT_UPDATE_UI( ID_MODEDIT_DELETE_PART, FOOTPRINT_EDIT_FRAME::OnUpdateLibSelected ) diff --git a/pcbnew/pcb_draw_panel_gal.cpp b/pcbnew/pcb_draw_panel_gal.cpp index 61abe32743..5a2dd4fed1 100644 --- a/pcbnew/pcb_draw_panel_gal.cpp +++ b/pcbnew/pcb_draw_panel_gal.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include @@ -356,6 +357,19 @@ void PCB_DRAW_PANEL_GAL::OnShow() { PCB_BASE_FRAME* frame = dynamic_cast( GetParent() ); + try + { + // Check if the current rendering backend can be properly initialized + m_view->UpdateItems(); + } + catch( const std::runtime_error& e ) + { + // Fallback to software renderer + DisplayError( frame, e.what() ); + bool use_gal = SwitchBackend( GAL_TYPE_CAIRO ); + frame->UseGalCanvas( use_gal ); + } + if( frame ) { SetTopLayer( frame->GetActiveLayer() ); diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 6c7b7e022f..2675ff9f2a 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -187,9 +187,9 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME ) EVT_MENU( ID_MENU_PCB_SHOW_3D_FRAME, PCB_EDIT_FRAME::Show3D_Frame ) // Switching canvases - EVT_MENU( ID_MENU_CANVAS_LEGACY, PCB_EDIT_FRAME::SwitchCanvas ) - EVT_MENU( ID_MENU_CANVAS_CAIRO, PCB_EDIT_FRAME::SwitchCanvas ) - EVT_MENU( ID_MENU_CANVAS_OPENGL, PCB_EDIT_FRAME::SwitchCanvas ) + EVT_MENU( ID_MENU_CANVAS_LEGACY, PCB_EDIT_FRAME::OnSwitchCanvas ) + EVT_MENU( ID_MENU_CANVAS_CAIRO, PCB_EDIT_FRAME::OnSwitchCanvas ) + EVT_MENU( ID_MENU_CANVAS_OPENGL, PCB_EDIT_FRAME::OnSwitchCanvas ) // Menu Get Design Rules Editor EVT_MENU( ID_MENU_PCB_SHOW_DESIGN_RULES_DIALOG, PCB_EDIT_FRAME::ShowDesignRulesEditor ) @@ -1176,10 +1176,10 @@ void PCB_EDIT_FRAME::OnLayerColorChange( wxCommandEvent& aEvent ) } -void PCB_EDIT_FRAME::SwitchCanvas( wxCommandEvent& aEvent ) +void PCB_EDIT_FRAME::OnSwitchCanvas( wxCommandEvent& aEvent ) { // switches currently used canvas (default / Cairo / OpenGL). - PCB_BASE_FRAME::SwitchCanvas( aEvent ); + PCB_BASE_FRAME::OnSwitchCanvas( aEvent ); // The base class method reinit the layers manager. // We must upate the layer widget to match board visibility states, diff --git a/pcbnew/wxPcbStruct.h b/pcbnew/wxPcbStruct.h index b0b36bb74f..41a2ee0234 100644 --- a/pcbnew/wxPcbStruct.h +++ b/pcbnew/wxPcbStruct.h @@ -116,7 +116,7 @@ protected: /** * switches currently used canvas (default / Cairo / OpenGL). */ - virtual void SwitchCanvas( wxCommandEvent& aEvent ) override; + virtual void OnSwitchCanvas( wxCommandEvent& aEvent ) override; #if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU) /**