mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-13 10:18:40 +12:00
rsx/qt: GsFrame improvements
- Identify minimize/restore events as separate from regular resize and do not react to them - Enable message queue consumption after loading the shaders cache. Also hides the frame in this step -- This fixes the 'start fullscreen' bug when running vulkan
This commit is contained in:
parent
1ffc1e82b0
commit
ce2b790d8f
5 changed files with 115 additions and 63 deletions
|
@ -631,6 +631,9 @@ void GLGSRender::on_init_thread()
|
||||||
{
|
{
|
||||||
GSRender::on_init_thread();
|
GSRender::on_init_thread();
|
||||||
|
|
||||||
|
m_frame->disable_wm_event_queue();
|
||||||
|
m_frame->hide();
|
||||||
|
|
||||||
gl::init();
|
gl::init();
|
||||||
|
|
||||||
//Enable adaptive vsync if vsync is requested
|
//Enable adaptive vsync if vsync is requested
|
||||||
|
@ -771,6 +774,9 @@ void GLGSRender::on_init_thread()
|
||||||
m_thread_id = std::this_thread::get_id();
|
m_thread_id = std::this_thread::get_id();
|
||||||
|
|
||||||
m_shaders_cache->load();
|
m_shaders_cache->load();
|
||||||
|
|
||||||
|
m_frame->enable_wm_event_queue();
|
||||||
|
m_frame->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGSRender::on_exit()
|
void GLGSRender::on_exit()
|
||||||
|
|
|
@ -24,7 +24,10 @@ enum wm_event
|
||||||
geometry_change_notice, //about to start resizing and/or moving the window
|
geometry_change_notice, //about to start resizing and/or moving the window
|
||||||
geometry_change_in_progress, //window being resized and/or moved
|
geometry_change_in_progress, //window being resized and/or moved
|
||||||
window_resized, //window was resized
|
window_resized, //window was resized
|
||||||
window_moved //window moved without resize
|
window_minimized, //window was minimized
|
||||||
|
window_restored, //window was restored from a minimized state
|
||||||
|
window_moved, //window moved without resize
|
||||||
|
window_visibility_changed
|
||||||
};
|
};
|
||||||
|
|
||||||
using RSXDebuggerPrograms = std::vector<RSXDebuggerProgram>;
|
using RSXDebuggerPrograms = std::vector<RSXDebuggerProgram>;
|
||||||
|
@ -58,6 +61,7 @@ protected:
|
||||||
//window manager event management
|
//window manager event management
|
||||||
wm_event m_raised_event;
|
wm_event m_raised_event;
|
||||||
std::atomic_bool wm_event_raised = {};
|
std::atomic_bool wm_event_raised = {};
|
||||||
|
std::atomic_bool wm_event_queue_enabled = {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//synchronize native window access
|
//synchronize native window access
|
||||||
|
@ -83,6 +87,16 @@ public:
|
||||||
|
|
||||||
return get_default_wm_event();
|
return get_default_wm_event();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void disable_wm_event_queue()
|
||||||
|
{
|
||||||
|
wm_event_queue_enabled.store(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable_wm_event_queue()
|
||||||
|
{
|
||||||
|
wm_event_queue_enabled.store(true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class GSRender : public rsx::thread
|
class GSRender : public rsx::thread
|
||||||
|
|
|
@ -1332,7 +1332,13 @@ void VKGSRender::on_init_thread()
|
||||||
GSRender::on_init_thread();
|
GSRender::on_init_thread();
|
||||||
rsx_thread = std::this_thread::get_id();
|
rsx_thread = std::this_thread::get_id();
|
||||||
|
|
||||||
|
m_frame->disable_wm_event_queue();
|
||||||
|
m_frame->hide();
|
||||||
|
|
||||||
m_shaders_cache->load(*m_device, pipeline_layout);
|
m_shaders_cache->load(*m_device, pipeline_layout);
|
||||||
|
|
||||||
|
m_frame->enable_wm_event_queue();
|
||||||
|
m_frame->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKGSRender::on_exit()
|
void VKGSRender::on_exit()
|
||||||
|
@ -1747,12 +1753,15 @@ void VKGSRender::do_local_task()
|
||||||
handled = true;
|
handled = true;
|
||||||
present_surface_dirty_flag = true;
|
present_surface_dirty_flag = true;
|
||||||
break;
|
break;
|
||||||
case wm_event::window_moved:
|
|
||||||
handled = true;
|
|
||||||
break;
|
|
||||||
case wm_event::geometry_change_in_progress:
|
case wm_event::geometry_change_in_progress:
|
||||||
timeout += 10; //extend timeout to wait for user to finish resizing
|
timeout += 10; //extend timeout to wait for user to finish resizing
|
||||||
break;
|
break;
|
||||||
|
case wm_event::window_visibility_changed:
|
||||||
|
case wm_event::window_minimized:
|
||||||
|
case wm_event::window_restored:
|
||||||
|
case wm_event::window_moved:
|
||||||
|
handled = true; //ignore these events as they do not alter client area
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handled)
|
if (handled)
|
||||||
|
|
|
@ -246,77 +246,99 @@ bool gs_frame::event(QEvent* ev)
|
||||||
bool gs_frame::nativeEvent(const QByteArray &eventType, void *message, long *result)
|
bool gs_frame::nativeEvent(const QByteArray &eventType, void *message, long *result)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
//Wait for consumer to clear notification pending flag
|
if (wm_event_queue_enabled.load(std::memory_order_consume))
|
||||||
while (wm_event_raised.load(std::memory_order_consume));
|
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(wm_event_lock);
|
//Wait for consumer to clear notification pending flag
|
||||||
MSG* msg = static_cast<MSG*>(message);
|
while (wm_event_raised.load(std::memory_order_consume));
|
||||||
switch (msg->message)
|
|
||||||
{
|
|
||||||
case WM_WINDOWPOSCHANGING:
|
|
||||||
{
|
|
||||||
const auto flags = reinterpret_cast<LPWINDOWPOS>(msg->lParam)->flags & SWP_NOSIZE;
|
|
||||||
if (m_in_sizing_event || flags != 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
//About to resize
|
|
||||||
m_in_sizing_event = true;
|
|
||||||
m_interactive_resize = false;
|
|
||||||
m_raised_event = wm_event::geometry_change_notice;
|
|
||||||
wm_event_raised.store(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case WM_WINDOWPOSCHANGED:
|
|
||||||
{
|
{
|
||||||
const auto flags = reinterpret_cast<LPWINDOWPOS>(msg->lParam)->flags & (SWP_NOSIZE | SWP_NOMOVE);
|
std::lock_guard<std::mutex> lock(wm_event_lock);
|
||||||
if (!m_in_sizing_event || m_user_interaction_active || flags == (SWP_NOSIZE | SWP_NOMOVE))
|
MSG* msg = static_cast<MSG*>(message);
|
||||||
break;
|
switch (msg->message)
|
||||||
|
|
||||||
if (flags & SWP_NOSIZE)
|
|
||||||
m_raised_event = wm_event::window_moved;
|
|
||||||
else
|
|
||||||
m_raised_event = wm_event::window_resized;
|
|
||||||
|
|
||||||
//Just finished resizing using maximize or SWP
|
|
||||||
m_in_sizing_event = false;
|
|
||||||
wm_event_raised.store(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case WM_ENTERSIZEMOVE:
|
|
||||||
m_user_interaction_active = true;
|
|
||||||
break;
|
|
||||||
case WM_EXITSIZEMOVE:
|
|
||||||
m_user_interaction_active = false;
|
|
||||||
if (m_in_sizing_event && !m_user_interaction_active)
|
|
||||||
{
|
{
|
||||||
//Just finished resizing using manual interaction. The corresponding WM_SIZE is consumed before this event fires
|
case WM_WINDOWPOSCHANGING:
|
||||||
m_raised_event = m_interactive_resize ? wm_event::window_resized : wm_event::window_moved;
|
{
|
||||||
|
const auto flags = reinterpret_cast<LPWINDOWPOS>(msg->lParam)->flags & SWP_NOSIZE;
|
||||||
|
if (m_in_sizing_event || flags != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
//About to resize
|
||||||
|
m_in_sizing_event = true;
|
||||||
|
m_interactive_resize = false;
|
||||||
|
m_raised_event = wm_event::geometry_change_notice;
|
||||||
|
wm_event_raised.store(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_WINDOWPOSCHANGED:
|
||||||
|
{
|
||||||
|
const auto flags = reinterpret_cast<LPWINDOWPOS>(msg->lParam)->flags & (SWP_NOSIZE | SWP_NOMOVE);
|
||||||
|
if (!m_in_sizing_event || m_user_interaction_active || flags == (SWP_NOSIZE | SWP_NOMOVE))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (flags & SWP_NOSIZE)
|
||||||
|
{
|
||||||
|
m_raised_event = wm_event::window_moved;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LPWINDOWPOS wpos = reinterpret_cast<LPWINDOWPOS>(msg->lParam);
|
||||||
|
if (wpos->cx <= GetSystemMetrics(SM_CXMINIMIZED) || wpos->cy <= GetSystemMetrics(SM_CYMINIMIZED))
|
||||||
|
{
|
||||||
|
//Minimize event
|
||||||
|
m_minimized = true;
|
||||||
|
m_raised_event = wm_event::window_minimized;
|
||||||
|
}
|
||||||
|
else if (m_minimized)
|
||||||
|
{
|
||||||
|
m_minimized = false;
|
||||||
|
m_raised_event = wm_event::window_restored;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_raised_event = wm_event::window_resized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Just finished resizing using maximize or SWP
|
||||||
m_in_sizing_event = false;
|
m_in_sizing_event = false;
|
||||||
wm_event_raised.store(true);
|
wm_event_raised.store(true);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
case WM_ENTERSIZEMOVE:
|
||||||
case WM_SIZE:
|
m_user_interaction_active = true;
|
||||||
{
|
break;
|
||||||
if (m_user_interaction_active)
|
case WM_EXITSIZEMOVE:
|
||||||
|
m_user_interaction_active = false;
|
||||||
|
if (m_in_sizing_event && !m_user_interaction_active)
|
||||||
|
{
|
||||||
|
//Just finished resizing using manual interaction. The corresponding WM_SIZE is consumed before this event fires
|
||||||
|
m_raised_event = m_interactive_resize ? wm_event::window_resized : wm_event::window_moved;
|
||||||
|
m_in_sizing_event = false;
|
||||||
|
wm_event_raised.store(true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_SIZE:
|
||||||
{
|
{
|
||||||
//Interaction is a resize not a move
|
if (m_user_interaction_active)
|
||||||
m_interactive_resize = true;
|
{
|
||||||
|
//Interaction is a resize not a move
|
||||||
|
m_interactive_resize = true;
|
||||||
|
}
|
||||||
|
else if (m_in_sizing_event)
|
||||||
|
{
|
||||||
|
//Any other unexpected resize mode will give an unconsumed WM_SIZE event
|
||||||
|
m_raised_event = wm_event::window_resized;
|
||||||
|
m_in_sizing_event = false;
|
||||||
|
wm_event_raised.store(true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (m_in_sizing_event)
|
|
||||||
{
|
|
||||||
//Any other unexpected resize mode will give an unconsumed WM_SIZE event
|
|
||||||
m_raised_event = wm_event::window_resized;
|
|
||||||
m_in_sizing_event = false;
|
|
||||||
wm_event_raised.store(true);
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Do not enter DefWndProc until the consumer has consumed the message
|
||||||
|
while (wm_event_raised.load(std::memory_order_consume));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Do not enter DefWndProc until the consumer has consumed the message
|
|
||||||
while (wm_event_raised.load(std::memory_order_consume));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Let the default handler deal with this. Only the notification is required
|
//Let the default handler deal with this. Only the notification is required
|
||||||
|
|
|
@ -17,6 +17,7 @@ class gs_frame : public QWindow, public GSFrameBase
|
||||||
bool m_in_sizing_event = false; //a signal that the window is about to be resized was received
|
bool m_in_sizing_event = false; //a signal that the window is about to be resized was received
|
||||||
bool m_user_interaction_active = false; //a signal indicating the window is being manually moved/resized was received
|
bool m_user_interaction_active = false; //a signal indicating the window is being manually moved/resized was received
|
||||||
bool m_interactive_resize = false; //resize signal received while dragging window
|
bool m_interactive_resize = false; //resize signal received while dragging window
|
||||||
|
bool m_minimized = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
gs_frame(const QString& title, int w, int h, QIcon appIcon, bool disableMouse);
|
gs_frame(const QString& title, int w, int h, QIcon appIcon, bool disableMouse);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue