From 475a39cb732b9f654f23c11c3e4d5fc4c62808b0 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Thu, 6 Sep 2018 19:42:53 -0700 Subject: [PATCH] Recreate the decoder when moving to a new display to allow Pacer to get the new refresh rate --- app/streaming/session.cpp | 10 ++++++- .../pacer/displaylinkvsyncsource.mm | 29 ++++--------------- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index 0b0ea91c..5cb99a5e 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -874,6 +874,8 @@ void Session::exec(int displayOriginX, int displayOriginY) SDL_GetError()); } + int currentDisplayIndex = SDL_GetWindowDisplayIndex(m_Window); + // Hijack this thread to be the SDL main thread. We have to do this // because we want to suspend all Qt processing until the stream is over. SDL_Event event; @@ -922,7 +924,12 @@ void Session::exec(int displayOriginX, int displayOriginY) // We use SDL_WINDOWEVENT_SIZE_CHANGED rather than SDL_WINDOWEVENT_RESIZED because the latter doesn't // seem to fire when switching from windowed to full-screen on X11. if (event.window.event != SDL_WINDOWEVENT_SIZE_CHANGED && event.window.event != SDL_WINDOWEVENT_SHOWN) { - break; + // Check that the window display hasn't changed. If it has, we want + // to recreate the decoder to allow it to adapt to the new display. + // This will allow Pacer to pull the new display refresh rate. + if (SDL_GetWindowDisplayIndex(m_Window) == currentDisplayIndex) { + break; + } } // Fall through @@ -940,6 +947,7 @@ void Session::exec(int displayOriginX, int displayOriginY) SDL_FlushEvent(SDL_WINDOWEVENT); // Update the window display mode based on our current monitor + currentDisplayIndex = SDL_GetWindowDisplayIndex(m_Window); updateOptimalWindowDisplayMode(); // Now that the old decoder is dead, flush any events it may diff --git a/app/streaming/video/ffmpeg-renderers/pacer/displaylinkvsyncsource.mm b/app/streaming/video/ffmpeg-renderers/pacer/displaylinkvsyncsource.mm index 1c39ea4e..234d685d 100644 --- a/app/streaming/video/ffmpeg-renderers/pacer/displaylinkvsyncsource.mm +++ b/app/streaming/video/ffmpeg-renderers/pacer/displaylinkvsyncsource.mm @@ -11,9 +11,7 @@ class DisplayLinkVsyncSource : public IVsyncSource public: DisplayLinkVsyncSource(Pacer* pacer) : m_Pacer(pacer), - m_Window(nullptr), - m_DisplayLink(nullptr), - m_DisplayId(UINT_MAX) + m_DisplayLink(nullptr) { } @@ -48,19 +46,6 @@ public: SDL_assert(displayLink == me->m_DisplayLink); - NSScreen* screen = [me->m_Window screen]; - if (screen != nullptr && getDisplayID(screen) != me->m_DisplayId) { - // CVDisplayLinkSetCurrentCGDisplay() will deadlock if called - // within a CVDisplayLink callback, so we just teardown the - // decoder (and pacer) to let it come back up on the new display. - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Streaming window display has changed; resetting decoder"); - SDL_Event event; - event.type = SDL_RENDER_TARGETS_RESET; - SDL_PushEvent(&event); - return kCVReturnSuccess; - } - // In my testing on macOS 10.13, this callback is invoked about 24 ms // prior to the specified v-sync time (now - vsyncTime). Since this is // greater than the standard v-sync interval (16 ms = 60 FPS), we will @@ -89,10 +74,9 @@ public: SDL_assert(info.subsystem == SDL_SYSWM_COCOA); - m_Window = info.info.cocoa.window; m_DisplayFps = displayFps; - NSScreen* screen = [m_Window screen]; + NSScreen* screen = [info.info.cocoa.window screen]; CVReturn status; if (screen == nullptr) { // Window not visible on any display, so use a @@ -104,11 +88,12 @@ public: status = CVDisplayLinkCreateWithActiveCGDisplays(&m_DisplayLink); } else { - m_DisplayId = getDisplayID(screen); + CGDirectDisplayID displayId; + displayId = getDisplayID(screen); SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NSWindow on display: %x", - m_DisplayId); - status = CVDisplayLinkCreateWithCGDisplay(m_DisplayId, &m_DisplayLink); + displayId); + status = CVDisplayLinkCreateWithCGDisplay(displayId, &m_DisplayLink); } if (status != kCVReturnSuccess) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, @@ -138,10 +123,8 @@ public: private: Pacer* m_Pacer; - NSWindow* m_Window; CVDisplayLinkRef m_DisplayLink; int m_DisplayFps; - CGDirectDisplayID m_DisplayId; }; IVsyncSource* DisplayLinkVsyncSourceFactory::createVsyncSource(Pacer* pacer) {