[videodb] remove unused seasons table from episode_view
[xbmc.git] / xbmc / windowing / windows / VideoSyncD3D.cpp
blob084c34e0e03838eff1bfec579d64b4051a115484
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "VideoSyncD3D.h"
11 #include "Utils/MathUtils.h"
12 #include "Utils/TimeUtils.h"
13 #include "cores/VideoPlayer/VideoReferenceClock.h"
14 #include "rendering/dx/DeviceResources.h"
15 #include "rendering/dx/RenderContext.h"
16 #include "utils/StringUtils.h"
17 #include "utils/XTimeUtils.h"
18 #include "utils/log.h"
19 #include "windowing/GraphicContext.h"
21 #include <mutex>
23 #ifdef TARGET_WINDOWS_STORE
24 #include <winrt/Windows.Graphics.Display.Core.h>
25 #endif
27 using namespace std::chrono_literals;
29 void CVideoSyncD3D::OnLostDisplay()
31 if (!m_displayLost)
33 m_displayLost = true;
34 m_lostEvent.Wait();
38 void CVideoSyncD3D::OnResetDisplay()
40 m_displayReset = true;
43 void CVideoSyncD3D::RefreshChanged()
45 m_displayReset = true;
48 bool CVideoSyncD3D::Setup()
50 CLog::Log(LOGDEBUG, "CVideoSyncD3D: Setting up Direct3d");
51 std::unique_lock<CCriticalSection> lock(CServiceBroker::GetWinSystem()->GetGfxContext());
52 DX::Windowing()->Register(this);
53 m_displayLost = false;
54 m_displayReset = false;
55 m_lostEvent.Reset();
57 // we need a high priority thread to get accurate timing
58 if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL))
59 CLog::Log(LOGDEBUG, "CVideoSyncD3D: SetThreadPriority failed");
61 CreateDXGIFactory1(IID_PPV_ARGS(m_factory.ReleaseAndGetAddressOf()));
63 Microsoft::WRL::ComPtr<IDXGIOutput> pOutput;
64 DX::DeviceResources::Get()->GetCachedOutputAndDesc(&pOutput, &m_outputDesc);
66 return true;
69 void CVideoSyncD3D::Run(CEvent& stopEvent)
71 int64_t Now;
72 int64_t LastVBlankTime;
73 int NrVBlanks;
74 double VBlankTime;
75 const int64_t systemFrequency = CurrentHostFrequency();
76 bool validVBlank{true};
78 // init the vblanktime
79 Now = CurrentHostCounter();
80 LastVBlankTime = Now;
82 while (!stopEvent.Signaled() && !m_displayLost && !m_displayReset)
84 // sleep until vblank
85 Microsoft::WRL::ComPtr<IDXGIOutput> pOutput;
86 DX::DeviceResources::Get()->GetCachedOutputAndDesc(pOutput.ReleaseAndGetAddressOf(),
87 &m_outputDesc);
89 const int64_t WaitForVBlankStartTime = CurrentHostCounter();
90 const HRESULT hr = pOutput ? pOutput->WaitForVBlank() : E_INVALIDARG;
91 const int64_t WaitForVBlankElapsedTime = CurrentHostCounter() - WaitForVBlankStartTime;
93 // WaitForVBlank() can return very quickly due to errors or screen sleeping
94 if (!SUCCEEDED(hr) || WaitForVBlankElapsedTime - (systemFrequency / 1000) <= 0)
96 if (SUCCEEDED(hr) && validVBlank)
97 CLog::LogF(LOGWARNING, "failed to detect vblank - screen asleep?");
99 if (!SUCCEEDED(hr))
100 CLog::LogF(LOGERROR, "error waiting for vblank, {}", DX::GetErrorDescription(hr));
102 validVBlank = false;
104 // Wait a while, until vblank may have come back. No need for accurate sleep.
105 ::Sleep(250);
106 continue;
108 else if (!validVBlank)
110 CLog::LogF(LOGWARNING, "vblank detected - resuming reference clock updates");
111 validVBlank = true;
114 // calculate how many vblanks happened
115 Now = CurrentHostCounter();
116 VBlankTime = (double)(Now - LastVBlankTime) / (double)systemFrequency;
117 NrVBlanks = MathUtils::round_int(VBlankTime * m_fps);
119 // update the vblank timestamp, update the clock and send a signal that we got a vblank
120 m_refClock->UpdateClock(NrVBlanks, Now);
122 // save the timestamp of this vblank so we can calculate how many vblanks happened next time
123 LastVBlankTime = Now;
125 if (!m_factory->IsCurrent())
127 CreateDXGIFactory1(IID_PPV_ARGS(m_factory.ReleaseAndGetAddressOf()));
129 float fps = m_fps;
130 if (fps != GetFps())
131 break;
135 m_lostEvent.Set();
136 while (!stopEvent.Signaled() && m_displayLost && !m_displayReset)
138 KODI::TIME::Sleep(10ms);
142 void CVideoSyncD3D::Cleanup()
144 CLog::Log(LOGDEBUG, "CVideoSyncD3D: Cleaning up Direct3d");
146 m_lostEvent.Set();
147 DX::Windowing()->Unregister(this);
150 float CVideoSyncD3D::GetFps()
152 #ifdef TARGET_WINDOWS_DESKTOP
153 DEVMODEW sDevMode = {};
154 sDevMode.dmSize = sizeof(sDevMode);
156 if (EnumDisplaySettingsW(m_outputDesc.DeviceName, ENUM_CURRENT_SETTINGS, &sDevMode))
158 if ((sDevMode.dmDisplayFrequency + 1) % 24 == 0 || (sDevMode.dmDisplayFrequency + 1) % 30 == 0)
159 m_fps = static_cast<float>(sDevMode.dmDisplayFrequency + 1) / 1.001f;
160 else
161 m_fps = static_cast<float>(sDevMode.dmDisplayFrequency);
163 if (sDevMode.dmDisplayFlags & DM_INTERLACED)
164 m_fps *= 2;
166 #else
167 using namespace winrt::Windows::Graphics::Display::Core;
169 auto hdmiInfo = HdmiDisplayInformation::GetForCurrentView();
170 if (hdmiInfo) // Xbox only
172 auto currentMode = hdmiInfo.GetCurrentDisplayMode();
173 m_fps = static_cast<float>(currentMode.RefreshRate());
175 #endif
177 if (m_fps == 0.0)
178 m_fps = 60.0f;
180 return m_fps;