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.
9 #include "WinSystemAndroid.h"
11 #include "OSScreenSaverAndroid.h"
12 #include "ServiceBroker.h"
13 #include "WinEventsAndroid.h"
14 #include "addons/interfaces/platform/android/System.h"
15 #include "cores/RetroPlayer/process/android/RPProcessInfoAndroid.h"
16 #include "cores/RetroPlayer/rendering/VideoRenderers/RPRendererOpenGLES.h"
17 #include "cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecAndroidMediaCodec.h"
18 #include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h"
19 #include "cores/VideoPlayer/Process/android/ProcessInfoAndroid.h"
20 #include "cores/VideoPlayer/VideoRenderers/HwDecRender/RendererMediaCodec.h"
21 #include "cores/VideoPlayer/VideoRenderers/HwDecRender/RendererMediaCodecSurface.h"
22 #include "guilib/DispResource.h"
23 #include "rendering/gles/ScreenshotSurfaceGLES.h"
24 #include "settings/DisplaySettings.h"
25 #include "settings/Settings.h"
26 #include "settings/SettingsComponent.h"
27 #include "utils/HDRCapabilities.h"
28 #include "utils/log.h"
29 #include "windowing/GraphicContext.h"
30 #include "windowing/Resolution.h"
32 #include "platform/android/activity/XBMCApp.h"
33 #include "platform/android/media/decoderfilter/MediaCodecDecoderFilterManager.h"
34 #include "platform/android/media/drm/MediaDrmCryptoSession.h"
41 #include "system_egl.h"
43 #include <EGL/eglplatform.h>
46 using namespace std::chrono_literals
;
48 CWinSystemAndroid::CWinSystemAndroid()
53 m_stereo_mode
= RENDER_STEREO_MODE_OFF
;
55 m_dispResetTimer
= new CTimer(this);
59 m_winEvents
= std::make_unique
<CWinEventsAndroid
>();
62 CWinSystemAndroid::~CWinSystemAndroid()
64 delete m_dispResetTimer
;
67 bool CWinSystemAndroid::InitWindowSystem()
69 m_nativeDisplay
= EGL_DEFAULT_DISPLAY
;
71 m_android
= new CAndroidUtils();
73 m_decoderFilterManager
= new(CMediaCodecDecoderFilterManager
);
74 CServiceBroker::RegisterDecoderFilterManager(m_decoderFilterManager
);
76 CDVDVideoCodecAndroidMediaCodec::Register();
77 CDVDAudioCodecAndroidMediaCodec::Register();
79 CLinuxRendererGLES::Register();
80 RETRO::CRPProcessInfoAndroid::Register();
81 RETRO::CRPProcessInfoAndroid::RegisterRendererFactory(new RETRO::CRendererFactoryOpenGLES
);
82 CRendererMediaCodec::Register();
83 CRendererMediaCodecSurface::Register();
84 ADDON::Interface_Android::Register();
85 DRM::CMediaDrmCryptoSession::Register();
86 VIDEOPLAYER::CProcessInfoAndroid::Register();
88 CScreenshotSurfaceGLES::Register();
90 return CWinSystemBase::InitWindowSystem();
93 bool CWinSystemAndroid::DestroyWindowSystem()
95 CLog::Log(LOGINFO
, "CWinSystemAndroid::{}", __FUNCTION__
);
100 CServiceBroker::RegisterDecoderFilterManager(nullptr);
101 delete m_decoderFilterManager
;
102 m_decoderFilterManager
= nullptr;
107 bool CWinSystemAndroid::CreateNewWindow(const std::string
& name
,
109 RESOLUTION_INFO
& res
)
111 m_nWidth
= res
.iWidth
;
112 m_nHeight
= res
.iHeight
;
113 m_displayWidth
= res
.iScreenWidth
;
114 m_displayHeight
= res
.iScreenHeight
;
115 m_fRefreshRate
= res
.fRefreshRate
;
117 m_dispResetTimer
->Stop();
118 m_HdmiModeTriggered
= false;
120 m_stereo_mode
= CServiceBroker::GetWinSystem()->GetGfxContext().GetStereoMode();
121 m_bFullScreen
= fullScreen
;
123 m_nativeWindow
= CXBMCApp::Get().GetNativeWindow(2000);
126 CLog::Log(LOGERROR
, "CWinSystemAndroid::CreateNewWindow: failed");
130 m_android
->SetNativeResolution(res
);
132 m_bWindowCreated
= true;
136 bool CWinSystemAndroid::DestroyWindow()
138 CLog::Log(LOGINFO
, "CWinSystemAndroid::{}", __FUNCTION__
);
139 m_nativeWindow
.reset();
140 m_bWindowCreated
= false;
144 void CWinSystemAndroid::UpdateResolutions()
146 UpdateResolutions(true);
149 void CWinSystemAndroid::UpdateResolutions(bool bUpdateDesktopRes
)
151 CWinSystemBase::UpdateResolutions();
153 std::vector
<RESOLUTION_INFO
> resolutions
;
154 if (!m_android
->ProbeResolutions(resolutions
) || resolutions
.empty())
156 CLog::Log(LOGWARNING
, "CWinSystemAndroid::{} failed.", __FUNCTION__
);
159 const RESOLUTION_INFO resWindow
= CDisplaySettings::GetInstance().GetResolutionInfo(RES_WINDOW
);
161 RESOLUTION_INFO resDesktop
;
162 if (bUpdateDesktopRes
)
164 // ProbeResolutions includes already all resolutions.
165 // Only get desktop resolution so we can replace Kodi's desktop res.
166 RESOLUTION_INFO curDisplay
;
167 if (m_android
->GetNativeResolution(&curDisplay
))
168 resDesktop
= curDisplay
;
172 // Do not replace Kodi's desktop res, just update the data.
173 resDesktop
= CDisplaySettings::GetInstance().GetResolutionInfo(RES_DESKTOP
);
176 CDisplaySettings::GetInstance().ClearCustomResolutions();
178 for (auto& res
: resolutions
)
180 CServiceBroker::GetWinSystem()->GetGfxContext().ResetOverscan(res
);
181 CDisplaySettings::GetInstance().AddResolutionInfo(res
);
183 if (resDesktop
.iScreenWidth
== res
.iScreenWidth
&&
184 resDesktop
.iScreenHeight
== res
.iScreenHeight
&&
185 (resDesktop
.dwFlags
& D3DPRESENTFLAG_MODEMASK
) == (res
.dwFlags
& D3DPRESENTFLAG_MODEMASK
) &&
186 std::fabs(resDesktop
.fRefreshRate
- res
.fRefreshRate
) < FLT_EPSILON
)
188 CDisplaySettings::GetInstance().GetResolutionInfo(RES_DESKTOP
) = res
;
191 if (resWindow
.iScreenWidth
== res
.iScreenWidth
&&
192 resWindow
.iScreenHeight
== res
.iScreenHeight
&&
193 (resWindow
.dwFlags
& D3DPRESENTFLAG_MODEMASK
) == (res
.dwFlags
& D3DPRESENTFLAG_MODEMASK
) &&
194 std::fabs(resWindow
.fRefreshRate
- res
.fRefreshRate
) < FLT_EPSILON
)
196 CDisplaySettings::GetInstance().GetResolutionInfo(RES_WINDOW
) = res
;
200 CDisplaySettings::GetInstance().ApplyCalibrations();
203 void CWinSystemAndroid::OnTimeout()
205 m_HdmiModeTriggered
= true;
208 void CWinSystemAndroid::InitiateModeChange()
211 std::chrono::milliseconds(CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(
212 "videoscreen.delayrefreshchange") *
217 m_dispResetTimer
->Stop();
218 m_dispResetTimer
->Start(delay
);
223 void CWinSystemAndroid::SetHdmiState(bool connected
)
225 std::unique_lock
<CCriticalSection
> lock(m_resourceSection
);
226 CLog::Log(LOGDEBUG
, "CWinSystemAndroid::SetHdmiState: state: {}", static_cast<int>(connected
));
230 if (m_dispResetTimer
->IsRunning())
232 // We stop the timer if OS supports HDMI_AUDIO_PLUG intent
233 // and configured delay is smaller than the time HDMI_PLUG took.
234 // Note that timer is always started with minimum of 2 seconds
235 // regardless if the configured delay is smaller
236 if (m_dispResetTimer
->GetElapsedMilliseconds() >=
237 CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(
238 "videoscreen.delayrefreshchange") *
240 m_dispResetTimer
->Stop();
245 for (auto resource
: m_resources
)
246 resource
->OnResetDisplay();
247 m_dispResetTimer
->Stop();
248 m_HdmiModeTriggered
= false;
252 for (auto resource
: m_resources
)
253 resource
->OnLostDisplay();
257 void CWinSystemAndroid::UpdateDisplayModes()
259 // re-fetch display modes
260 m_android
->UpdateDisplayModes();
264 // update display settings
265 UpdateResolutions(false);
269 bool CWinSystemAndroid::Minimize()
271 return CXBMCApp::Get().moveTaskToBack(true);
274 bool CWinSystemAndroid::Hide()
279 bool CWinSystemAndroid::Show(bool raise
)
284 void CWinSystemAndroid::Register(IDispResource
*resource
)
286 std::unique_lock
<CCriticalSection
> lock(m_resourceSection
);
287 m_resources
.push_back(resource
);
290 void CWinSystemAndroid::Unregister(IDispResource
*resource
)
292 std::unique_lock
<CCriticalSection
> lock(m_resourceSection
);
293 std::vector
<IDispResource
*>::iterator i
= find(m_resources
.begin(), m_resources
.end(), resource
);
294 if (i
!= m_resources
.end())
295 m_resources
.erase(i
);
298 void CWinSystemAndroid::MessagePush(XBMC_Event
*newEvent
)
300 dynamic_cast<CWinEventsAndroid
&>(*m_winEvents
).MessagePush(newEvent
);
303 bool CWinSystemAndroid::MessagePump()
305 return m_winEvents
->MessagePump();
308 bool CWinSystemAndroid::IsHDRDisplay()
310 return m_android
->IsHDRDisplay();
313 std::unique_ptr
<WINDOWING::IOSScreenSaver
> CWinSystemAndroid::GetOSScreenSaverImpl()
315 std::unique_ptr
<KODI::WINDOWING::IOSScreenSaver
> ret(new COSScreenSaverAndroid());
319 CHDRCapabilities
CWinSystemAndroid::GetDisplayHDRCapabilities() const
321 return CAndroidUtils::GetDisplayHDRCapabilities();
324 float CWinSystemAndroid::GetGuiSdrPeakLuminance() const
326 const auto settings
= CServiceBroker::GetSettingsComponent()->GetSettings();
327 const int guiSdrPeak
= settings
->GetInt(CSettings::SETTING_VIDEOSCREEN_GUISDRPEAKLUMINANCE
);
329 return ((0.7f
* guiSdrPeak
+ 30.0f
) / 100.0f
);