1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #include "WinSystemGbmGLESContext.h"
10 
11 #include "OptionalsReg.h"
12 #include "cores/RetroPlayer/process/gbm/RPProcessInfoGbm.h"
13 #include "cores/RetroPlayer/rendering/VideoRenderers/RPRendererDMA.h"
14 #include "cores/RetroPlayer/rendering/VideoRenderers/RPRendererOpenGLES.h"
15 #include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h"
16 #include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h"
17 #include "cores/VideoPlayer/Process/gbm/ProcessInfoGBM.h"
18 #include "cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.h"
19 #include "cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIMEGLES.h"
20 #include "cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h"
21 #include "cores/VideoPlayer/VideoRenderers/RenderFactory.h"
22 #include "rendering/gles/ScreenshotSurfaceGLES.h"
23 #include "utils/BufferObjectFactory.h"
24 #include "utils/DMAHeapBufferObject.h"
25 #include "utils/DumbBufferObject.h"
26 #include "utils/GBMBufferObject.h"
27 #include "utils/UDMABufferObject.h"
28 #include "utils/XTimeUtils.h"
29 #include "utils/log.h"
30 #include "windowing/WindowSystemFactory.h"
31 
32 #include <gbm.h>
33 
34 using namespace KODI::WINDOWING::GBM;
35 
CWinSystemGbmGLESContext()36 CWinSystemGbmGLESContext::CWinSystemGbmGLESContext()
37 : CWinSystemGbmEGLContext(EGL_PLATFORM_GBM_MESA, "EGL_MESA_platform_gbm")
38 {}
39 
Register()40 void CWinSystemGbmGLESContext::Register()
41 {
42   CWindowSystemFactory::RegisterWindowSystem(CreateWinSystem, "gbm");
43 }
44 
CreateWinSystem()45 std::unique_ptr<CWinSystemBase> CWinSystemGbmGLESContext::CreateWinSystem()
46 {
47   return std::make_unique<CWinSystemGbmGLESContext>();
48 }
49 
InitWindowSystem()50 bool CWinSystemGbmGLESContext::InitWindowSystem()
51 {
52   VIDEOPLAYER::CRendererFactory::ClearRenderer();
53   CDVDFactoryCodec::ClearHWAccels();
54   CLinuxRendererGLES::Register();
55   RETRO::CRPProcessInfoGbm::Register();
56   RETRO::CRPProcessInfoGbm::RegisterRendererFactory(new RETRO::CRendererFactoryDMA);
57   RETRO::CRPProcessInfoGbm::RegisterRendererFactory(new RETRO::CRendererFactoryOpenGLES);
58 
59   if (!CWinSystemGbmEGLContext::InitWindowSystemEGL(EGL_OPENGL_ES2_BIT, EGL_OPENGL_ES_API))
60   {
61     return false;
62   }
63 
64   bool general, deepColor;
65   m_vaapiProxy.reset(GBM::VaapiProxyCreate(m_DRM->GetRenderNodeFileDescriptor()));
66   GBM::VaapiProxyConfig(m_vaapiProxy.get(), m_eglContext.GetEGLDisplay());
67   GBM::VAAPIRegisterRender(m_vaapiProxy.get(), general, deepColor);
68 
69   if (general)
70   {
71     GBM::VAAPIRegister(m_vaapiProxy.get(), deepColor);
72   }
73 
74   CRendererDRMPRIMEGLES::Register();
75   CRendererDRMPRIME::Register();
76   CDVDVideoCodecDRMPRIME::Register();
77   VIDEOPLAYER::CProcessInfoGBM::Register();
78 
79   CScreenshotSurfaceGLES::Register();
80 
81   CBufferObjectFactory::ClearBufferObjects();
82   CDumbBufferObject::Register();
83 #if defined(HAS_GBM_BO_MAP)
84   CGBMBufferObject::Register();
85 #endif
86 #if defined(HAVE_LINUX_MEMFD) && defined(HAVE_LINUX_UDMABUF)
87   CUDMABufferObject::Register();
88 #endif
89 #if defined(HAVE_LINUX_DMA_HEAP)
90   CDMAHeapBufferObject::Register();
91 #endif
92 
93   return true;
94 }
95 
SetFullScreen(bool fullScreen,RESOLUTION_INFO & res,bool blankOtherDisplays)96 bool CWinSystemGbmGLESContext::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays)
97 {
98   if (res.iWidth != m_nWidth ||
99       res.iHeight != m_nHeight)
100   {
101     CLog::Log(LOGDEBUG, "CWinSystemGbmGLESContext::%s - resolution changed, creating a new window", __FUNCTION__);
102     CreateNewWindow("", fullScreen, res);
103   }
104 
105   if (!m_eglContext.TrySwapBuffers())
106   {
107     CEGLUtils::Log(LOGERROR, "eglSwapBuffers failed");
108     throw std::runtime_error("eglSwapBuffers failed");
109   }
110 
111   CWinSystemGbm::SetFullScreen(fullScreen, res, blankOtherDisplays);
112   CRenderSystemGLES::ResetRenderSystem(res.iWidth, res.iHeight);
113 
114   return true;
115 }
116 
PresentRender(bool rendered,bool videoLayer)117 void CWinSystemGbmGLESContext::PresentRender(bool rendered, bool videoLayer)
118 {
119   if (!m_bRenderCreated)
120     return;
121 
122   if (rendered || videoLayer)
123   {
124     if (rendered)
125     {
126       if (!m_eglContext.TrySwapBuffers())
127       {
128         CEGLUtils::Log(LOGERROR, "eglSwapBuffers failed");
129         throw std::runtime_error("eglSwapBuffers failed");
130       }
131     }
132     CWinSystemGbm::FlipPage(rendered, videoLayer);
133 
134     if (m_dispReset && m_dispResetTimer.IsTimePast())
135     {
136       CLog::Log(LOGDEBUG, "CWinSystemGbmGLESContext::%s - Sending display reset to all clients",
137                 __FUNCTION__);
138       m_dispReset = false;
139       CSingleLock lock(m_resourceSection);
140 
141       for (auto resource : m_resources)
142         resource->OnResetDisplay();
143     }
144   }
145   else
146   {
147     KODI::TIME::Sleep(10);
148   }
149 }
150 
CreateContext()151 bool CWinSystemGbmGLESContext::CreateContext()
152 {
153   CEGLAttributesVec contextAttribs;
154   contextAttribs.Add({{EGL_CONTEXT_CLIENT_VERSION, 2}});
155 
156   if (!m_eglContext.CreateContext(contextAttribs))
157   {
158     CLog::Log(LOGERROR, "EGL context creation failed");
159     return false;
160   }
161   return true;
162 }
163