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.
11 #include "ServiceBroker.h"
12 #include "guilib/DispResource.h"
14 #include "guilib/GUIFontTTFGL.h"
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"
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()
38 CDisplaySettings::GetInstance().ApplyCalibrations();
40 CResolutionUtils::PrintWhitelist();
45 bool CWinSystemBase::DestroyWindowSystem()
47 m_screenSaverManager
.reset();
51 void CWinSystemBase::UpdateDesktopResolution(RESOLUTION_INFO
& newRes
,
52 const std::string
& output
,
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
);
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
,
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)
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
152 RESOLUTION_WHR res
= {width
, height
, screenWidth
, screenHeight
, flags
, static_cast<int>(addindex
),
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
);
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
);
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
238 bool CWinSystemBase::UseLimitedColor()
243 std::string
CWinSystemBase::GetClipboardText(void)
248 int CWinSystemBase::NoOfBuffers(void)
250 int buffers
= CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_VIDEOSCREEN_NOOFBUFFERS
);
254 KODI::WINDOWING::COSScreenSaverManager
* CWinSystemBase::GetOSScreenSaver()
256 if (!m_screenSaverManager
)
258 auto impl
= GetOSScreenSaverImpl();
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()
288 std::unique_lock
<CCriticalSection
> lock(m_renderLoopSection
);
289 for (auto i
= m_renderLoopClients
.begin(); i
!= m_renderLoopClients
.end(); ++i
)
294 CGraphicContext
& CWinSystemBase::GetGfxContext() const
296 return *m_gfxContext
;
299 std::shared_ptr
<CDPMSSupport
> CWinSystemBase::GetDPMSManager()
304 bool CWinSystemBase::IsHDRDisplaySettingEnabled()
309 const auto settings
= CServiceBroker::GetSettingsComponent()->GetSettings();
311 return (settings
&& settings
->GetBool(SETTING_WINSYSTEM_IS_HDR_DISPLAY
));
314 bool CWinSystemBase::IsVideoSuperResolutionSettingEnabled()
316 if (!SupportsVideoSuperResolution())
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();
338 return std::pair
<bool, int>{settings
->GetBool(CSettings::SETTING_VIDEOSCREEN_DITHER
),
339 settings
->GetInt(CSettings::SETTING_VIDEOSCREEN_DITHERDEPTH
)};