Преглед изворни кода

Merge pull request #4976 from comex/poll-events

Overhaul EmuWindow::PollEvents to fix yuzu-cmd calling SDL_PollEvents off main thread
Rodrigo Locatti пре 5 година
родитељ
комит
0e15c68f54

+ 2 - 2
src/core/frontend/emu_window.h

@@ -102,8 +102,8 @@ public:
         float render_surface_scale = 1.0f;
     };
 
-    /// Polls window events
-    virtual void PollEvents() = 0;
+    /// Called from GPU thread when a frame is displayed.
+    virtual void OnFrameDisplayed() {}
 
     /**
      * Returns a GraphicsContext that the frontend provides to be used for rendering.

+ 1 - 1
src/video_core/renderer_opengl/renderer_opengl.cpp

@@ -151,8 +151,8 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
 
     rasterizer->TickFrame();
 
-    render_window.PollEvents();
     context->SwapBuffers();
+    render_window.OnFrameDisplayed();
 }
 
 void RendererOpenGL::PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer) {

+ 1 - 3
src/video_core/renderer_vulkan/renderer_vulkan.cpp

@@ -252,8 +252,6 @@ RendererVulkan::~RendererVulkan() {
 }
 
 void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
-    render_window.PollEvents();
-
     if (!framebuffer) {
         return;
     }
@@ -283,7 +281,7 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
         rasterizer->TickFrame();
     }
 
-    render_window.PollEvents();
+    render_window.OnFrameDisplayed();
 }
 
 bool RendererVulkan::Init() {

+ 1 - 1
src/yuzu/bootmanager.cpp

@@ -314,7 +314,7 @@ GRenderWindow::~GRenderWindow() {
     input_subsystem->Shutdown();
 }
 
-void GRenderWindow::PollEvents() {
+void GRenderWindow::OnFrameDisplayed() {
     if (!first_frame) {
         first_frame = true;
         emit FirstFrameDisplayed();

+ 1 - 1
src/yuzu/bootmanager.h

@@ -131,7 +131,7 @@ public:
     ~GRenderWindow() override;
 
     // EmuWindow implementation.
-    void PollEvents() override;
+    void OnFrameDisplayed() override;
     bool IsShown() const override;
     std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override;
 

+ 51 - 49
src/yuzu_cmd/emu_window/emu_window_sdl2.cpp

@@ -121,62 +121,64 @@ void EmuWindow_SDL2::Fullscreen() {
     SDL_MaximizeWindow(render_window);
 }
 
-void EmuWindow_SDL2::PollEvents() {
+void EmuWindow_SDL2::WaitEvent() {
+    // Called on main thread
     SDL_Event event;
 
-    // SDL_PollEvent returns 0 when there are no more events in the event queue
-    while (SDL_PollEvent(&event)) {
-        switch (event.type) {
-        case SDL_WINDOWEVENT:
-            switch (event.window.event) {
-            case SDL_WINDOWEVENT_SIZE_CHANGED:
-            case SDL_WINDOWEVENT_RESIZED:
-            case SDL_WINDOWEVENT_MAXIMIZED:
-            case SDL_WINDOWEVENT_RESTORED:
-                OnResize();
-                break;
-            case SDL_WINDOWEVENT_MINIMIZED:
-            case SDL_WINDOWEVENT_EXPOSED:
-                is_shown = event.window.event == SDL_WINDOWEVENT_EXPOSED;
-                OnResize();
-                break;
-            case SDL_WINDOWEVENT_CLOSE:
-                is_open = false;
-                break;
-            }
-            break;
-        case SDL_KEYDOWN:
-        case SDL_KEYUP:
-            OnKeyEvent(static_cast<int>(event.key.keysym.scancode), event.key.state);
-            break;
-        case SDL_MOUSEMOTION:
-            // ignore if it came from touch
-            if (event.button.which != SDL_TOUCH_MOUSEID)
-                OnMouseMotion(event.motion.x, event.motion.y);
-            break;
-        case SDL_MOUSEBUTTONDOWN:
-        case SDL_MOUSEBUTTONUP:
-            // ignore if it came from touch
-            if (event.button.which != SDL_TOUCH_MOUSEID) {
-                OnMouseButton(event.button.button, event.button.state, event.button.x,
-                              event.button.y);
-            }
-            break;
-        case SDL_FINGERDOWN:
-            OnFingerDown(event.tfinger.x, event.tfinger.y);
-            break;
-        case SDL_FINGERMOTION:
-            OnFingerMotion(event.tfinger.x, event.tfinger.y);
+    if (!SDL_WaitEvent(&event)) {
+        LOG_CRITICAL(Frontend, "SDL_WaitEvent failed: {}", SDL_GetError());
+        exit(1);
+    }
+
+    switch (event.type) {
+    case SDL_WINDOWEVENT:
+        switch (event.window.event) {
+        case SDL_WINDOWEVENT_SIZE_CHANGED:
+        case SDL_WINDOWEVENT_RESIZED:
+        case SDL_WINDOWEVENT_MAXIMIZED:
+        case SDL_WINDOWEVENT_RESTORED:
+            OnResize();
             break;
-        case SDL_FINGERUP:
-            OnFingerUp();
+        case SDL_WINDOWEVENT_MINIMIZED:
+        case SDL_WINDOWEVENT_EXPOSED:
+            is_shown = event.window.event == SDL_WINDOWEVENT_EXPOSED;
+            OnResize();
             break;
-        case SDL_QUIT:
+        case SDL_WINDOWEVENT_CLOSE:
             is_open = false;
             break;
-        default:
-            break;
         }
+        break;
+    case SDL_KEYDOWN:
+    case SDL_KEYUP:
+        OnKeyEvent(static_cast<int>(event.key.keysym.scancode), event.key.state);
+        break;
+    case SDL_MOUSEMOTION:
+        // ignore if it came from touch
+        if (event.button.which != SDL_TOUCH_MOUSEID)
+            OnMouseMotion(event.motion.x, event.motion.y);
+        break;
+    case SDL_MOUSEBUTTONDOWN:
+    case SDL_MOUSEBUTTONUP:
+        // ignore if it came from touch
+        if (event.button.which != SDL_TOUCH_MOUSEID) {
+            OnMouseButton(event.button.button, event.button.state, event.button.x, event.button.y);
+        }
+        break;
+    case SDL_FINGERDOWN:
+        OnFingerDown(event.tfinger.x, event.tfinger.y);
+        break;
+    case SDL_FINGERMOTION:
+        OnFingerMotion(event.tfinger.x, event.tfinger.y);
+        break;
+    case SDL_FINGERUP:
+        OnFingerUp();
+        break;
+    case SDL_QUIT:
+        is_open = false;
+        break;
+    default:
+        break;
     }
 
     const u32 current_time = SDL_GetTicks();

+ 10 - 10
src/yuzu_cmd/emu_window/emu_window_sdl2.h

@@ -23,38 +23,38 @@ public:
     explicit EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem);
     ~EmuWindow_SDL2();
 
-    /// Polls window events
-    void PollEvents() override;
-
     /// Whether the window is still open, and a close request hasn't yet been sent
     bool IsOpen() const;
 
     /// Returns if window is shown (not minimized)
     bool IsShown() const override;
 
+    /// Wait for the next event on the main thread.
+    void WaitEvent();
+
 protected:
-    /// Called by PollEvents when a key is pressed or released.
+    /// Called by WaitEvent when a key is pressed or released.
     void OnKeyEvent(int key, u8 state);
 
-    /// Called by PollEvents when the mouse moves.
+    /// Called by WaitEvent when the mouse moves.
     void OnMouseMotion(s32 x, s32 y);
 
-    /// Called by PollEvents when a mouse button is pressed or released
+    /// Called by WaitEvent when a mouse button is pressed or released
     void OnMouseButton(u32 button, u8 state, s32 x, s32 y);
 
     /// Translates pixel position (0..1) to pixel positions
     std::pair<unsigned, unsigned> TouchToPixelPos(float touch_x, float touch_y) const;
 
-    /// Called by PollEvents when a finger starts touching the touchscreen
+    /// Called by WaitEvent when a finger starts touching the touchscreen
     void OnFingerDown(float x, float y);
 
-    /// Called by PollEvents when a finger moves while touching the touchscreen
+    /// Called by WaitEvent when a finger moves while touching the touchscreen
     void OnFingerMotion(float x, float y);
 
-    /// Called by PollEvents when a finger stops touching the touchscreen
+    /// Called by WaitEvent when a finger stops touching the touchscreen
     void OnFingerUp();
 
-    /// Called by PollEvents when any event that may cause the window to be resized occurs
+    /// Called by WaitEvent when any event that may cause the window to be resized occurs
     void OnResize();
 
     /// Called when user passes the fullscreen parameter flag

+ 1 - 1
src/yuzu_cmd/yuzu.cpp

@@ -242,7 +242,7 @@ int main(int argc, char** argv) {
 
     void(system.Run());
     while (emu_window->IsOpen()) {
-        std::this_thread::sleep_for(std::chrono::milliseconds(1));
+        emu_window->WaitEvent();
     }
     void(system.Pause());
     system.Shutdown();

+ 0 - 2
src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp

@@ -109,8 +109,6 @@ EmuWindow_SDL2_Hide::~EmuWindow_SDL2_Hide() {
     SDL_Quit();
 }
 
-void EmuWindow_SDL2_Hide::PollEvents() {}
-
 bool EmuWindow_SDL2_Hide::IsShown() const {
     return false;
 }

+ 0 - 3
src/yuzu_tester/emu_window/emu_window_sdl2_hide.h

@@ -17,9 +17,6 @@ public:
     explicit EmuWindow_SDL2_Hide();
     ~EmuWindow_SDL2_Hide();
 
-    /// Polls window events
-    void PollEvents() override;
-
     /// Whether the screen is being shown or not.
     bool IsShown() const override;