[videodb] remove unused seasons table from episode_view
[xbmc.git] / xbmc / windowing / gbm / WinSystemGbm.cpp
blob72497a2156843466392600d4d7d5ebffd86b1ea9
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 "WinSystemGbm.h"
11 #include "GBMDPMSSupport.h"
12 #include "OptionalsReg.h"
13 #include "ServiceBroker.h"
14 #include "VideoSyncGbm.h"
15 #include "cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h"
16 #include "cores/VideoPlayer/VideoReferenceClock.h"
17 #include "drm/DRMAtomic.h"
18 #include "drm/DRMLegacy.h"
19 #include "drm/OffScreenModeSetting.h"
20 #include "messaging/ApplicationMessenger.h"
21 #include "settings/DisplaySettings.h"
22 #include "settings/Settings.h"
23 #include "settings/SettingsComponent.h"
24 #include "settings/lib/Setting.h"
25 #include "utils/DisplayInfo.h"
26 #include "utils/Map.h"
27 #include "utils/StringUtils.h"
28 #include "utils/log.h"
29 #include "windowing/GraphicContext.h"
31 #include <mutex>
32 #include <string.h>
34 #ifndef HAVE_HDR_OUTPUT_METADATA
35 // HDR structs is copied from linux include/linux/hdmi.h
36 struct hdr_metadata_infoframe
38 uint8_t eotf;
39 uint8_t metadata_type;
40 struct
42 uint16_t x, y;
43 } display_primaries[3];
44 struct
46 uint16_t x, y;
47 } white_point;
48 uint16_t max_display_mastering_luminance;
49 uint16_t min_display_mastering_luminance;
50 uint16_t max_cll;
51 uint16_t max_fall;
53 struct hdr_output_metadata
55 uint32_t metadata_type;
56 union
58 struct hdr_metadata_infoframe hdmi_metadata_type1;
61 #endif
63 using namespace KODI::WINDOWING::GBM;
65 using namespace std::chrono_literals;
67 namespace
70 // These map to the definitions in the linux kernel
71 // drivers/gpu/drm/drm_connector.c
73 constexpr auto ColorimetryMap = make_map<KODI::UTILS::Colorimetry, std::string_view>({
74 {KODI::UTILS::Colorimetry::DEFAULT, "Default"},
75 {KODI::UTILS::Colorimetry::XVYCC_601, "XVYCC_601"},
76 {KODI::UTILS::Colorimetry::XVYCC_709, "XVYCC_709"},
77 {KODI::UTILS::Colorimetry::SYCC_601, "SYCC_601"},
78 {KODI::UTILS::Colorimetry::OPYCC_601, "opYCC_601"},
79 {KODI::UTILS::Colorimetry::OPRGB, "opRGB"},
80 {KODI::UTILS::Colorimetry::BT2020_CYCC, "BT2020_CYCC"},
81 {KODI::UTILS::Colorimetry::BT2020_YCC, "BT2020_YCC"},
82 {KODI::UTILS::Colorimetry::BT2020_RGB, "BT2020_RGB"},
83 {KODI::UTILS::Colorimetry::ST2113_RGB, "Default"},
84 {KODI::UTILS::Colorimetry::ICTCP, "Default"},
85 });
86 } // namespace
88 CWinSystemGbm::CWinSystemGbm() :
89 m_DRM(nullptr),
90 m_GBM(new CGBMUtils),
91 m_libinput(new CLibInputHandler)
93 m_dpms = std::make_shared<CGBMDPMSSupport>();
94 m_libinput->Start();
97 CWinSystemGbm::~CWinSystemGbm() = default;
99 bool CWinSystemGbm::InitWindowSystem()
101 const char* x11 = getenv("DISPLAY");
102 const char* wayland = getenv("WAYLAND_DISPLAY");
103 if (x11 || wayland)
105 CLog::Log(LOGDEBUG, "CWinSystemGbm::{} - not allowed to run GBM under a window manager",
106 __FUNCTION__);
107 return false;
110 m_DRM = std::make_shared<CDRMAtomic>();
112 if (!m_DRM->InitDrm())
114 CLog::Log(LOGERROR, "CWinSystemGbm::{} - failed to initialize Atomic DRM", __FUNCTION__);
115 m_DRM.reset();
117 m_DRM = std::make_shared<CDRMLegacy>();
119 if (!m_DRM->InitDrm())
121 CLog::Log(LOGERROR, "CWinSystemGbm::{} - failed to initialize Legacy DRM", __FUNCTION__);
122 m_DRM.reset();
124 m_DRM = std::make_shared<COffScreenModeSetting>();
125 if (!m_DRM->InitDrm())
127 CLog::Log(LOGERROR, "CWinSystemGbm::{} - failed to initialize off screen DRM",
128 __FUNCTION__);
129 m_DRM.reset();
130 return false;
135 CDRMConnector* connector = m_DRM->GetConnector();
136 if (connector)
138 std::vector<uint8_t> edid = connector->GetEDID();
139 if (!edid.empty())
141 m_info = UTILS::CDisplayInfo::Create(edid);
145 if (!m_GBM->CreateDevice(m_DRM->GetFileDescriptor()))
147 m_GBM.reset();
148 return false;
151 auto settingsComponent = CServiceBroker::GetSettingsComponent();
152 if (!settingsComponent)
153 return false;
155 auto settings = settingsComponent->GetSettings();
156 if (!settings)
157 return false;
159 auto setting = settings->GetSetting(CSettings::SETTING_VIDEOSCREEN_LIMITEDRANGE);
160 if (setting)
161 setting->SetVisible(true);
163 setting = settings->GetSetting("videoscreen.limitguisize");
164 if (setting)
165 setting->SetVisible(true);
167 CLog::Log(LOGDEBUG, "CWinSystemGbm::{} - initialized DRM", __FUNCTION__);
168 return CWinSystemBase::InitWindowSystem();
171 bool CWinSystemGbm::DestroyWindowSystem()
173 CLog::Log(LOGDEBUG, "CWinSystemGbm::{} - deinitialized DRM", __FUNCTION__);
175 m_libinput.reset();
177 return true;
180 void CWinSystemGbm::UpdateResolutions()
182 RESOLUTION_INFO current = m_DRM->GetCurrentMode();
184 auto resolutions = m_DRM->GetModes();
185 if (resolutions.empty())
187 CDisplaySettings::GetInstance().ClearCustomResolutions();
189 CServiceBroker::GetWinSystem()->GetGfxContext().ResetOverscan(current);
190 CDisplaySettings::GetInstance().AddResolutionInfo(current);
191 CDisplaySettings::GetInstance().GetResolutionInfo(RES_DESKTOP) = current;
193 CLog::Log(LOGINFO, "Found resolution {}x{} with {}x{}{} @ {:f} Hz", current.iWidth,
194 current.iHeight, current.iScreenWidth, current.iScreenHeight,
195 current.dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : "", current.fRefreshRate);
197 else
199 CDisplaySettings::GetInstance().ClearCustomResolutions();
201 for (auto &res : resolutions)
203 CServiceBroker::GetWinSystem()->GetGfxContext().ResetOverscan(res);
204 CDisplaySettings::GetInstance().AddResolutionInfo(res);
206 if (current.iScreenWidth == res.iScreenWidth &&
207 current.iScreenHeight == res.iScreenHeight &&
208 current.iWidth == res.iWidth &&
209 current.iHeight == res.iHeight &&
210 current.fRefreshRate == res.fRefreshRate &&
211 current.dwFlags == res.dwFlags)
213 CDisplaySettings::GetInstance().GetResolutionInfo(RES_DESKTOP) = res;
216 CLog::Log(LOGINFO, "Found resolution {}x{} with {}x{}{} @ {:f} Hz", res.iWidth, res.iHeight,
217 res.iScreenWidth, res.iScreenHeight,
218 res.dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : "", res.fRefreshRate);
222 CDisplaySettings::GetInstance().ApplyCalibrations();
225 bool CWinSystemGbm::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop)
227 return true;
230 bool CWinSystemGbm::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays)
232 // Notify other subsystems that we will change resolution
233 OnLostDevice();
235 if(!m_DRM->SetMode(res))
237 CLog::Log(LOGERROR, "CWinSystemGbm::{} - failed to set DRM mode", __FUNCTION__);
238 return false;
241 struct gbm_bo *bo = nullptr;
243 if (!std::dynamic_pointer_cast<CDRMAtomic>(m_DRM))
245 bo = m_GBM->GetDevice().GetSurface().LockFrontBuffer().Get();
248 auto result = m_DRM->SetVideoMode(res, bo);
250 auto delay =
251 std::chrono::milliseconds(CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(
252 "videoscreen.delayrefreshchange") *
253 100);
254 if (delay > 0ms)
255 m_dispResetTimer.Set(delay);
257 return result;
260 bool CWinSystemGbm::DisplayHardwareScalingEnabled()
262 auto drmAtomic = std::dynamic_pointer_cast<CDRMAtomic>(m_DRM);
263 if (drmAtomic && drmAtomic->DisplayHardwareScalingEnabled())
264 return true;
266 return false;
269 void CWinSystemGbm::UpdateDisplayHardwareScaling(const RESOLUTION_INFO& resInfo)
271 if (!DisplayHardwareScalingEnabled())
272 return;
274 //! @todo The PR that made the res struct constant was abandoned due to drama.
275 // It should be const-corrected and changed here.
276 RESOLUTION_INFO& resMutable = const_cast<RESOLUTION_INFO&>(resInfo);
278 SetFullScreen(true, resMutable, false);
281 void CWinSystemGbm::FlipPage(bool rendered, bool videoLayer, bool async)
283 if (m_videoLayerBridge && !videoLayer)
285 // disable video plane when video layer no longer is active
286 m_videoLayerBridge->Disable();
289 struct gbm_bo *bo = nullptr;
291 if (rendered)
293 bo = m_GBM->GetDevice().GetSurface().LockFrontBuffer().Get();
296 m_DRM->FlipPage(bo, rendered, videoLayer, async);
298 if (m_videoLayerBridge && !videoLayer)
300 // delete video layer bridge when video layer no longer is active
301 m_videoLayerBridge.reset();
305 bool CWinSystemGbm::UseLimitedColor()
307 return CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_VIDEOSCREEN_LIMITEDRANGE);
310 bool CWinSystemGbm::Hide()
312 bool ret = m_DRM->SetActive(false);
313 FlipPage(false, false, false);
314 return ret;
317 bool CWinSystemGbm::Show(bool raise)
319 bool ret = m_DRM->SetActive(true);
320 FlipPage(false, false, false);
321 return ret;
324 void CWinSystemGbm::Register(IDispResource *resource)
326 std::unique_lock<CCriticalSection> lock(m_resourceSection);
327 m_resources.push_back(resource);
330 void CWinSystemGbm::Unregister(IDispResource *resource)
332 std::unique_lock<CCriticalSection> lock(m_resourceSection);
333 std::vector<IDispResource*>::iterator i = find(m_resources.begin(), m_resources.end(), resource);
334 if (i != m_resources.end())
336 m_resources.erase(i);
340 void CWinSystemGbm::OnLostDevice()
342 CLog::Log(LOGDEBUG, "{} - notify display change event", __FUNCTION__);
343 m_dispReset = true;
345 std::unique_lock<CCriticalSection> lock(m_resourceSection);
346 for (auto resource : m_resources)
347 resource->OnLostDisplay();
350 std::unique_ptr<CVideoSync> CWinSystemGbm::GetVideoSync(CVideoReferenceClock* clock)
352 return std::make_unique<CVideoSyncGbm>(clock);
355 std::vector<std::string> CWinSystemGbm::GetConnectedOutputs()
357 return m_DRM->GetConnectedConnectorNames();
360 bool CWinSystemGbm::SetHDR(const VideoPicture* videoPicture)
362 auto settingsComponent = CServiceBroker::GetSettingsComponent();
363 if (!settingsComponent)
364 return false;
366 auto settings = settingsComponent->GetSettings();
367 if (!settings)
368 return false;
370 if (!settings->GetBool(SETTING_WINSYSTEM_IS_HDR_DISPLAY))
371 return false;
373 auto drm = std::dynamic_pointer_cast<CDRMAtomic>(m_DRM);
374 if (!drm)
375 return false;
377 auto connector = drm->GetConnector();
378 if (!connector)
379 return false;
381 if (!videoPicture)
383 if (connector->SupportsProperty("Colorspace"))
385 std::optional<uint64_t> colorspace = connector->GetPropertyValue("Colorspace", "Default");
386 if (colorspace)
388 CLog::LogF(LOGDEBUG, "setting connector colorspace to Default");
389 drm->AddProperty(connector, "Colorspace", colorspace.value());
390 drm->SetActive(true);
394 if (connector->SupportsProperty("HDR_OUTPUT_METADATA"))
396 drm->AddProperty(connector, "HDR_OUTPUT_METADATA", 0);
397 drm->SetActive(true);
399 if (m_hdr_blob_id)
400 drmModeDestroyPropertyBlob(drm->GetFileDescriptor(), m_hdr_blob_id);
401 m_hdr_blob_id = 0;
404 return false;
407 KODI::UTILS::Colorimetry colorimetry = DRMPRIME::GetColorimetry(*videoPicture);
409 if (connector->SupportsProperty("Colorspace") && m_info &&
410 m_info->SupportsColorimetry(colorimetry))
412 std::optional<uint64_t> colorspace =
413 connector->GetPropertyValue("Colorspace", ColorimetryMap.at(colorimetry));
414 if (colorspace)
416 CLog::LogF(LOGDEBUG, "setting connector colorspace to {}", ColorimetryMap.at(colorimetry));
417 drm->AddProperty(connector, "Colorspace", colorspace.value());
418 drm->SetActive(true);
422 KODI::UTILS::Eotf eotf = DRMPRIME::GetEOTF(*videoPicture);
424 if (connector->SupportsProperty("HDR_OUTPUT_METADATA") && m_info &&
425 m_info->SupportsHDRStaticMetadataType1() && m_info->SupportsEOTF(eotf))
427 hdr_output_metadata hdr_metadata = {};
429 hdr_metadata.metadata_type = DRMPRIME::HDMI_STATIC_METADATA_TYPE1;
430 hdr_metadata.hdmi_metadata_type1.eotf = static_cast<uint8_t>(eotf);
431 hdr_metadata.hdmi_metadata_type1.metadata_type = DRMPRIME::HDMI_STATIC_METADATA_TYPE1;
433 if (m_hdr_blob_id)
434 drmModeDestroyPropertyBlob(drm->GetFileDescriptor(), m_hdr_blob_id);
435 m_hdr_blob_id = 0;
437 if (hdr_metadata.hdmi_metadata_type1.eotf)
439 const AVMasteringDisplayMetadata* mdmd = DRMPRIME::GetMasteringDisplayMetadata(*videoPicture);
440 if (mdmd && mdmd->has_primaries)
442 // Convert to unsigned 16-bit values in units of 0.00002,
443 // where 0x0000 represents zero and 0xC350 represents 1.0000
444 for (int i = 0; i < 3; i++)
446 hdr_metadata.hdmi_metadata_type1.display_primaries[i].x =
447 std::round(av_q2d(mdmd->display_primaries[i][0]) * 50000.0);
448 hdr_metadata.hdmi_metadata_type1.display_primaries[i].y =
449 std::round(av_q2d(mdmd->display_primaries[i][1]) * 50000.0);
451 CLog::Log(LOGDEBUG, LOGVIDEO, "CWinSystemGbm::{} - display_primaries[{}].x: {}",
452 __FUNCTION__, i, hdr_metadata.hdmi_metadata_type1.display_primaries[i].x);
453 CLog::Log(LOGDEBUG, LOGVIDEO, "CWinSystemGbm::{} - display_primaries[{}].y: {}",
454 __FUNCTION__, i, hdr_metadata.hdmi_metadata_type1.display_primaries[i].y);
456 hdr_metadata.hdmi_metadata_type1.white_point.x =
457 std::round(av_q2d(mdmd->white_point[0]) * 50000.0);
458 hdr_metadata.hdmi_metadata_type1.white_point.y =
459 std::round(av_q2d(mdmd->white_point[1]) * 50000.0);
461 CLog::Log(LOGDEBUG, LOGVIDEO, "CWinSystemGbm::{} - white_point.x: {}", __FUNCTION__,
462 hdr_metadata.hdmi_metadata_type1.white_point.x);
463 CLog::Log(LOGDEBUG, LOGVIDEO, "CWinSystemGbm::{} - white_point.y: {}", __FUNCTION__,
464 hdr_metadata.hdmi_metadata_type1.white_point.y);
466 if (mdmd && mdmd->has_luminance)
468 // Convert to unsigned 16-bit value in units of 1 cd/m2,
469 // where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2
470 hdr_metadata.hdmi_metadata_type1.max_display_mastering_luminance =
471 std::round(av_q2d(mdmd->max_luminance));
473 // Convert to unsigned 16-bit value in units of 0.0001 cd/m2,
474 // where 0x0001 represents 0.0001 cd/m2 and 0xFFFF represents 6.5535 cd/m2
475 hdr_metadata.hdmi_metadata_type1.min_display_mastering_luminance =
476 std::round(av_q2d(mdmd->min_luminance) * 10000.0);
478 CLog::Log(LOGDEBUG, LOGVIDEO, "CWinSystemGbm::{} - max_display_mastering_luminance: {}",
479 __FUNCTION__, hdr_metadata.hdmi_metadata_type1.max_display_mastering_luminance);
480 CLog::Log(LOGDEBUG, LOGVIDEO, "CWinSystemGbm::{} - min_display_mastering_luminance: {}",
481 __FUNCTION__, hdr_metadata.hdmi_metadata_type1.min_display_mastering_luminance);
484 const AVContentLightMetadata* clmd = DRMPRIME::GetContentLightMetadata(*videoPicture);
485 if (clmd)
487 hdr_metadata.hdmi_metadata_type1.max_cll = clmd->MaxCLL;
488 hdr_metadata.hdmi_metadata_type1.max_fall = clmd->MaxFALL;
490 CLog::Log(LOGDEBUG, LOGVIDEO, "CWinSystemGbm::{} - max_cll: {}", __FUNCTION__,
491 hdr_metadata.hdmi_metadata_type1.max_cll);
492 CLog::Log(LOGDEBUG, LOGVIDEO, "CWinSystemGbm::{} - max_fall: {}", __FUNCTION__,
493 hdr_metadata.hdmi_metadata_type1.max_fall);
496 drmModeCreatePropertyBlob(drm->GetFileDescriptor(), &hdr_metadata, sizeof(hdr_metadata),
497 &m_hdr_blob_id);
500 drm->AddProperty(connector, "HDR_OUTPUT_METADATA", m_hdr_blob_id);
501 drm->SetActive(true);
504 return m_hdr_blob_id != 0;
507 bool CWinSystemGbm::IsHDRDisplay()
509 auto drm = std::dynamic_pointer_cast<CDRMAtomic>(m_DRM);
510 if (!drm)
511 return false;
513 auto connector = drm->GetConnector();
514 if (!connector)
515 return false;
517 return connector->SupportsProperty("HDR_OUTPUT_METADATA") && m_info &&
518 m_info->SupportsHDRStaticMetadataType1();
521 CHDRCapabilities CWinSystemGbm::GetDisplayHDRCapabilities() const
523 if (!m_info)
524 return {};
526 CHDRCapabilities caps;
528 if (m_info->SupportsEOTF(UTILS::Eotf::PQ))
529 caps.SetHDR10();
531 if (m_info->SupportsEOTF(UTILS::Eotf::HLG))
532 caps.SetHLG();
534 return caps;