KiCad PCB EDA Suite
Loading...
Searching...
No Matches
swapchain_controller.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
21#include <rhi/render_thread.h>
22#include <trace_helpers.h>
23
24#include <wx/log.h>
25
26
27namespace KIGFX
28{
29
30
32 RHI_WINDOW_ID aWindowId ) :
33 m_renderThread( aRenderThread ),
34 m_windowId( aWindowId )
35{
36}
37
38
40{
41 if( m_created )
42 OnCloseSync( std::chrono::milliseconds( 1000 ) );
43}
44
45
47 uint32_t aWidth, uint32_t aHeight, float aDpiScale )
48{
49 auto now = RHI_PHASE_STALL_TRACKER::CLOCK::now();
50
51 if( !m_created )
52 {
53 wxLogTrace( traceRhi, wxS( "SwapchainCtrl: OnPaint first call windowId=%u %ux%u "
54 "dpi=%.1f native=%p" ),
55 m_windowId, aWidth, aHeight, aDpiScale, aHandle.nativeHandle );
56
58 create.windowId = m_windowId;
59 create.nativeHandle = aHandle;
60 create.width = aWidth;
61 create.height = aHeight;
62 create.dpiScale = aDpiScale;
64
65 if( !m_renderThread.SubmitControl( create ) )
66 {
67 wxLogTrace( traceRhi, wxS( "SwapchainCtrl: SubmitControl(CREATE) FAILED" ) );
68 return false;
69 }
70
71 m_created = true;
72 m_width = aWidth;
73 m_height = aHeight;
74 m_dpiScale = aDpiScale;
75 }
76
78 req.windowId = m_windowId;
81
82 bool ok = m_renderThread.SubmitControl( req );
83
84 if( !ok )
85 {
86 wxLogTrace( traceRhi, wxS( "SwapchainCtrl: SubmitControl(FRAME_REQUEST) FAILED "
87 "windowId=%u gen=%llu" ),
88 m_windowId, static_cast<unsigned long long>( m_generation - 1 ) );
89 }
90 else if( ( m_generation - m_lastLoggedGeneration ) >= 60 )
91 {
92 wxLogTrace( traceRhi, wxS( "SwapchainCtrl: OnPaint windowId=%u gen=%llu" ),
93 m_windowId, static_cast<unsigned long long>( m_generation - 1 ) );
95 }
96
97 int rtPhase = m_renderThread.GetLoopPhase();
99
100 if( stall.shouldLog )
101 {
102 wxLogTrace( traceRhi, wxS( "SwapchainCtrl: suspected render-thread stall "
103 "windowId=%u phase=%d gen=%llu queued=%llu age=%lldms" ),
104 m_windowId, stall.phase,
105 static_cast<unsigned long long>( m_generation ),
106 static_cast<unsigned long long>( stall.stalledGenerations ),
107 static_cast<long long>( stall.stallAge.count() ) );
108 }
109
110 return ok;
111}
112
113
114bool SWAPCHAIN_CONTROLLER::OnResize( uint32_t aWidth, uint32_t aHeight, float aDpiScale )
115{
116 if( !m_created )
117 {
118 wxLogTrace( traceRhi, wxS( "SwapchainCtrl: OnResize SKIPPED (not created) "
119 "windowId=%u %ux%u" ),
120 m_windowId, aWidth, aHeight );
121 return false;
122 }
123
124 if( aWidth == m_width && aHeight == m_height && aDpiScale == m_dpiScale )
125 return true;
126
127 wxLogTrace( traceRhi, wxS( "SwapchainCtrl: OnResize windowId=%u %ux%u -> %ux%u "
128 "dpi=%.1f" ),
129 m_windowId, m_width, m_height, aWidth, aHeight, aDpiScale );
130
131 m_width = aWidth;
132 m_height = aHeight;
133 m_dpiScale = aDpiScale;
134
136 resize.windowId = m_windowId;
137 resize.width = aWidth;
138 resize.height = aHeight;
139 resize.dpiScale = aDpiScale;
140
141 return m_renderThread.SubmitControl( resize );
142}
143
144
146{
147 wxLogTrace( traceRhi, wxS( "SwapchainCtrl: OnClose windowId=%u (created=%s)" ),
148 m_windowId, m_created ? "yes" : "no" );
149
150 if( !m_created )
151 return false;
152
154 destroy.windowId = m_windowId;
155
156 bool ok = m_renderThread.SubmitControl( destroy );
157 m_created = false;
158
159 wxLogTrace( traceRhi, wxS( "SwapchainCtrl: OnClose submit=%s" ), ok ? "OK" : "FAILED" );
160
161 return ok;
162}
163
164
165bool SWAPCHAIN_CONTROLLER::OnCloseSync( std::chrono::milliseconds aTimeout )
166{
167 wxLogTrace( traceRhi, wxS( "SwapchainCtrl: OnCloseSync windowId=%u timeout=%lldms" ),
168 m_windowId, static_cast<long long>( aTimeout.count() ) );
169
170 if( !OnClose() )
171 return false;
172
173 bool ok = m_renderThread.WaitForFence( aTimeout );
174
175 wxLogTrace( traceRhi, wxS( "SwapchainCtrl: OnCloseSync fence=%s" ),
176 ok ? "signaled" : "TIMEOUT" );
177
178 return ok;
179}
180
181
182} // namespace KIGFX
Thread that owns the RHI device.
SWAPCHAIN_CONTROLLER(RENDER_THREAD &aRenderThread, RHI_WINDOW_ID aWindowId)
RHI_PHASE_STALL_TRACKER m_phaseStallTracker
bool OnResize(uint32_t aWidth, uint32_t aHeight, float aDpiScale=1.0f)
bool OnCloseSync(std::chrono::milliseconds aTimeout=std::chrono::milliseconds(2000))
Close and wait for the render thread to release the window's GPU resources, so the native window can ...
bool OnPaint(const RHI_NATIVE_WINDOW_HANDLE &aHandle, uint32_t aWidth, uint32_t aHeight, float aDpiScale=1.0f)
The first call creates the swapchain.
const wxChar *const traceRhi
Flag to enable debug output of the RHI rendering backend.
The Cairo implementation of the graphics abstraction layer.
Definition eda_group.h:30
RHI_PHASE_STALL_RESULT EvaluateRenderThreadPhaseStall(RHI_PHASE_STALL_TRACKER &aTracker, int aPhase, uint64_t aGeneration, RHI_PHASE_STALL_TRACKER::CLOCK::time_point aNow, std::chrono::milliseconds aStallThreshold=std::chrono::milliseconds(1000), uint64_t aGenerationThreshold=60, std::chrono::milliseconds aRepeatThreshold=std::chrono::milliseconds(1000))
uint32_t RHI_WINDOW_ID
Routes control commands to a swapchain.
float refreshHz
display refresh rate, 0 when unknown
KIGFX::FRAME_MAILBOX * frame2DMailbox
Owned by the panel.
RHI_NATIVE_WINDOW_HANDLE nativeHandle
Platform-agnostic wrapper for a native window handle.
Definition rhi_surface.h:45
wxLogTrace helper definitions.