[Test] Added tests for CUtil::SplitParams
[xbmc.git] / xbmc / windowing / WinSystem.cpp
blobf1d40bf2f02728cfd55283e06a72510e03b4ea91
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 "WinSystem.h"
11 #include "ServiceBroker.h"
12 #include "guilib/DispResource.h"
13 #if HAS_GLES
14 #include "guilib/GUIFontTTFGL.h"
15 #endif
16 #include "powermanagement/DPMSSupport.h"
17 #include "settings/DisplaySettings.h"
18 #include "settings/Settings.h"
19 #include "settings/SettingsComponent.h"
20 #include "settings/lib/Setting.h"
21 #include "utils/StringUtils.h"
22 #include "windowing/GraphicContext.h"
24 #include <memory>
25 #include <mutex>
27 const char* CWinSystemBase::SETTING_WINSYSTEM_IS_HDR_DISPLAY = "winsystem.ishdrdisplay";
29 CWinSystemBase::CWinSystemBase() : m_gfxContext(std::make_unique<CGraphicContext>())
33 CWinSystemBase::~CWinSystemBase() = default;
35 bool CWinSystemBase::InitWindowSystem()
37 UpdateResolutions();
38 CDisplaySettings::GetInstance().ApplyCalibrations();
40 CResolutionUtils::PrintWhitelist();
42 return true;
45 bool CWinSystemBase::DestroyWindowSystem()
47 m_screenSaverManager.reset();
48 return false;
51 void CWinSystemBase::UpdateDesktopResolution(RESOLUTION_INFO& newRes,
52 const std::string& output,
53 int width,
54 int height,
55 int screenWidth,
56 int screenHeight,
57 float refreshRate,
58 uint32_t dwFlags)
60 newRes.Overscan.left = 0;
61 newRes.Overscan.top = 0;
62 newRes.Overscan.right = width;
63 newRes.Overscan.bottom = height;
64 newRes.bFullScreen = true;
65 newRes.iSubtitles = height;
66 newRes.dwFlags = dwFlags;
67 newRes.fRefreshRate = refreshRate;
68 newRes.fPixelRatio = 1.0f;
69 newRes.iWidth = width;
70 newRes.iHeight = height;
71 newRes.iScreenWidth = screenWidth;
72 newRes.iScreenHeight = screenHeight;
73 newRes.strMode = StringUtils::Format("{}: {}x{}", output, width, height);
74 if (refreshRate > 1)
75 newRes.strMode += StringUtils::Format(" @ {:.2f}Hz", refreshRate);
76 if (dwFlags & D3DPRESENTFLAG_INTERLACED)
77 newRes.strMode += "i";
78 if (dwFlags & D3DPRESENTFLAG_MODE3DTB)
79 newRes.strMode += "tab";
80 if (dwFlags & D3DPRESENTFLAG_MODE3DSBS)
81 newRes.strMode += "sbs";
82 newRes.strOutput = output;
85 void CWinSystemBase::UpdateDesktopResolution(RESOLUTION_INFO& newRes,
86 const std::string& output,
87 int width,
88 int height,
89 float refreshRate,
90 uint32_t dwFlags)
92 UpdateDesktopResolution(newRes, output, width, height, width, height, refreshRate, dwFlags);
95 void CWinSystemBase::UpdateResolutions()
97 // add the window res - defaults are fine.
98 RESOLUTION_INFO& window = CDisplaySettings::GetInstance().GetResolutionInfo(RES_WINDOW);
99 window.bFullScreen = false;
100 if (window.iWidth == 0)
101 window.iWidth = 720;
102 if (window.iHeight == 0)
103 window.iHeight = 480;
104 window.iScreenWidth = window.iWidth;
105 window.iScreenHeight = window.iHeight;
106 if (window.iSubtitles == 0)
107 window.iSubtitles = window.iHeight;
108 window.fPixelRatio = 1.0f;
109 window.strMode = "Windowed";
112 void CWinSystemBase::SetWindowResolution(int width, int height)
114 RESOLUTION_INFO& window = CDisplaySettings::GetInstance().GetResolutionInfo(RES_WINDOW);
115 window.iWidth = width;
116 window.iHeight = height;
117 window.iScreenWidth = width;
118 window.iScreenHeight = height;
119 window.iSubtitles = window.iHeight;
120 CServiceBroker::GetWinSystem()->GetGfxContext().ResetOverscan(window);
123 static void AddResolution(std::vector<RESOLUTION_WHR> &resolutions, unsigned int addindex, float bestRefreshrate)
125 RESOLUTION_INFO resInfo = CDisplaySettings::GetInstance().GetResolutionInfo(addindex);
126 const int width = resInfo.iWidth;
127 const int height = resInfo.iHeight;
128 const int screenWidth = resInfo.iScreenWidth;
129 const int screenHeight = resInfo.iScreenHeight;
130 int flags = resInfo.dwFlags & D3DPRESENTFLAG_MODEMASK;
131 const std::string id = resInfo.strId;
132 float refreshrate = resInfo.fRefreshRate;
134 // don't touch RES_DESKTOP
135 for (auto& resolution : resolutions)
137 if (resolution.width == width && resolution.height == height &&
138 resolution.m_screenWidth == screenWidth && resolution.m_screenHeight == screenHeight &&
139 (resolution.flags & D3DPRESENTFLAG_MODEMASK) == flags)
141 // check if the refresh rate of this resolution is better suited than
142 // the refresh rate of the resolution with the same width/height/interlaced
143 // property and if so replace it
144 if (bestRefreshrate > 0.0f && refreshrate == bestRefreshrate)
145 resolution.ResInfo_Index = addindex;
147 // no need to add the resolution again
148 return;
152 RESOLUTION_WHR res = {width, height, screenWidth, screenHeight, flags, static_cast<int>(addindex),
153 id};
154 resolutions.emplace_back(res);
157 static bool resSortPredicate(const RESOLUTION_WHR& i, const RESOLUTION_WHR& j)
159 // note: this comparison must obey "strict weak ordering"
160 // a "!=" on the flags comparison resulted in memory corruption
161 return ( i.width < j.width
162 || (i.width == j.width && i.height < j.height)
163 || (i.width == j.width && i.height == j.height && i.flags < j.flags) );
166 std::vector<RESOLUTION_WHR> CWinSystemBase::ScreenResolutions(float refreshrate)
168 std::vector<RESOLUTION_WHR> resolutions;
170 for (unsigned int idx = RES_CUSTOM; idx < CDisplaySettings::GetInstance().ResolutionInfoSize(); idx++)
172 RESOLUTION_INFO info = CDisplaySettings::GetInstance().GetResolutionInfo(idx);
173 AddResolution(resolutions, idx, refreshrate);
176 // Can't assume a sort order
177 sort(resolutions.begin(), resolutions.end(), resSortPredicate);
179 return resolutions;
182 static void AddRefreshRate(std::vector<REFRESHRATE> &refreshrates, unsigned int addindex)
184 float RefreshRate = CDisplaySettings::GetInstance().GetResolutionInfo(addindex).fRefreshRate;
186 for (unsigned int idx = 0; idx < refreshrates.size(); idx++)
187 if ( refreshrates[idx].RefreshRate == RefreshRate)
188 return; // already taken care of.
190 REFRESHRATE rr = {RefreshRate, (int)addindex};
191 refreshrates.push_back(rr);
194 static bool rrSortPredicate(REFRESHRATE i, REFRESHRATE j)
196 return (i.RefreshRate < j.RefreshRate);
199 std::vector<REFRESHRATE> CWinSystemBase::RefreshRates(int width, int height, uint32_t dwFlags)
201 std::vector<REFRESHRATE> refreshrates;
203 for (unsigned int idx = RES_DESKTOP; idx < CDisplaySettings::GetInstance().ResolutionInfoSize(); idx++)
205 if (CDisplaySettings::GetInstance().GetResolutionInfo(idx).iScreenWidth == width &&
206 CDisplaySettings::GetInstance().GetResolutionInfo(idx).iScreenHeight == height &&
207 (CDisplaySettings::GetInstance().GetResolutionInfo(idx).dwFlags & D3DPRESENTFLAG_MODEMASK) == (dwFlags & D3DPRESENTFLAG_MODEMASK))
208 AddRefreshRate(refreshrates, idx);
211 // Can't assume a sort order
212 sort(refreshrates.begin(), refreshrates.end(), rrSortPredicate);
214 return refreshrates;
217 REFRESHRATE CWinSystemBase::DefaultRefreshRate(const std::vector<REFRESHRATE>& rates)
219 REFRESHRATE bestmatch = rates[0];
220 float bestfitness = -1.0f;
221 float targetfps = CDisplaySettings::GetInstance().GetResolutionInfo(RES_DESKTOP).fRefreshRate;
223 for (unsigned i = 0; i < rates.size(); i++)
225 float fitness = fabs(targetfps - rates[i].RefreshRate);
227 if (bestfitness <0 || fitness < bestfitness)
229 bestfitness = fitness;
230 bestmatch = rates[i];
231 if (bestfitness == 0.0f) // perfect match
232 break;
235 return bestmatch;
238 bool CWinSystemBase::UseLimitedColor()
240 return false;
243 std::string CWinSystemBase::GetClipboardText(void)
245 return "";
248 int CWinSystemBase::NoOfBuffers(void)
250 int buffers = CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_VIDEOSCREEN_NOOFBUFFERS);
251 return buffers;
254 KODI::WINDOWING::COSScreenSaverManager* CWinSystemBase::GetOSScreenSaver()
256 if (!m_screenSaverManager)
258 auto impl = GetOSScreenSaverImpl();
259 if (impl)
261 m_screenSaverManager =
262 std::make_unique<KODI::WINDOWING::COSScreenSaverManager>(std::move(impl));
266 return m_screenSaverManager.get();
269 void CWinSystemBase::RegisterRenderLoop(IRenderLoop *client)
271 std::unique_lock<CCriticalSection> lock(m_renderLoopSection);
272 m_renderLoopClients.push_back(client);
275 void CWinSystemBase::UnregisterRenderLoop(IRenderLoop *client)
277 std::unique_lock<CCriticalSection> lock(m_renderLoopSection);
278 auto i = find(m_renderLoopClients.begin(), m_renderLoopClients.end(), client);
279 if (i != m_renderLoopClients.end())
280 m_renderLoopClients.erase(i);
283 void CWinSystemBase::DriveRenderLoop()
285 MessagePump();
288 std::unique_lock<CCriticalSection> lock(m_renderLoopSection);
289 for (auto i = m_renderLoopClients.begin(); i != m_renderLoopClients.end(); ++i)
290 (*i)->FrameMove();
294 CGraphicContext& CWinSystemBase::GetGfxContext() const
296 return *m_gfxContext;
299 std::shared_ptr<CDPMSSupport> CWinSystemBase::GetDPMSManager()
301 return m_dpms;
304 bool CWinSystemBase::IsHDRDisplaySettingEnabled()
306 if (!IsHDRDisplay())
307 return false;
309 const auto settings = CServiceBroker::GetSettingsComponent()->GetSettings();
311 return (settings && settings->GetBool(SETTING_WINSYSTEM_IS_HDR_DISPLAY));
314 bool CWinSystemBase::IsVideoSuperResolutionSettingEnabled()
316 if (!SupportsVideoSuperResolution())
317 return false;
319 const auto settings = CServiceBroker::GetSettingsComponent()->GetSettings();
321 return (settings && settings->GetBool(CSettings::SETTING_VIDEOPLAYER_USESUPERRESOLUTION));
324 bool CWinSystemBase::IsHighPrecisionProcessingSettingEnabled()
326 const auto settings = CServiceBroker::GetSettingsComponent()->GetSettings();
328 return (settings && settings->GetBool(CSettings::SETTING_VIDEOPLAYER_HIGHPRECISIONPROCESSING));
331 std::pair<bool, int> CWinSystemBase::GetDitherSettings()
333 const auto settings = CServiceBroker::GetSettingsComponent()->GetSettings();
335 if (!settings)
336 return {};
338 return std::pair<bool, int>{settings->GetBool(CSettings::SETTING_VIDEOSCREEN_DITHER),
339 settings->GetInt(CSettings::SETTING_VIDEOSCREEN_DITHERDEPTH)};