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 "WinSystemX11GLESContext.h"
11 #include "GLContextEGL.h"
12 #include "OptionalsReg.h"
13 #include "X11DPMSSupport.h"
14 #include "application/ApplicationComponents.h"
15 #include "application/ApplicationSkinHandling.h"
16 #include "cores/RetroPlayer/process/X11/RPProcessInfoX11.h"
17 #include "cores/RetroPlayer/rendering/VideoRenderers/RPRendererOpenGLES.h"
18 #include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h"
19 #include "cores/VideoPlayer/Process/X11/ProcessInfoX11.h"
20 #include "cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h"
21 #include "cores/VideoPlayer/VideoRenderers/RenderFactory.h"
22 #include "guilib/DispResource.h"
23 #include "utils/log.h"
24 #include "windowing/GraphicContext.h"
25 #include "windowing/WindowSystemFactory.h"
30 using namespace KODI::WINDOWING::X11
;
32 void CWinSystemX11GLESContext::Register()
34 KODI::WINDOWING::CWindowSystemFactory::RegisterWindowSystem(CreateWinSystem
, "x11");
37 std::unique_ptr
<CWinSystemBase
> CWinSystemX11GLESContext::CreateWinSystem()
39 return std::make_unique
<CWinSystemX11GLESContext
>();
42 CWinSystemX11GLESContext::~CWinSystemX11GLESContext()
47 void CWinSystemX11GLESContext::PresentRenderImpl(bool rendered
)
49 if (rendered
&& m_pGLContext
)
50 m_pGLContext
->SwapBuffers();
52 if (m_delayDispReset
&& m_dispResetTimer
.IsTimePast())
54 m_delayDispReset
= false;
55 std::unique_lock
<CCriticalSection
> lock(m_resourceSection
);
56 // tell any shared resources
57 for (std::vector
<IDispResource
*>::iterator i
= m_resources
.begin(); i
!= m_resources
.end(); ++i
)
58 (*i
)->OnResetDisplay();
62 void CWinSystemX11GLESContext::SetVSyncImpl(bool enable
)
64 m_pGLContext
->SetVSync(enable
);
67 bool CWinSystemX11GLESContext::IsExtSupported(const char* extension
) const
69 if (strncmp(extension
, m_pGLContext
->ExtPrefix().c_str(), 4) != 0)
70 return CRenderSystemGLES::IsExtSupported(extension
);
72 return m_pGLContext
->IsExtSupported(extension
);
75 EGLDisplay
CWinSystemX11GLESContext::GetEGLDisplay() const
77 return m_pGLContext
->m_eglDisplay
;
80 EGLSurface
CWinSystemX11GLESContext::GetEGLSurface() const
82 return m_pGLContext
->m_eglSurface
;
85 EGLContext
CWinSystemX11GLESContext::GetEGLContext() const
87 return m_pGLContext
->m_eglContext
;
90 EGLConfig
CWinSystemX11GLESContext::GetEGLConfig() const
92 return m_pGLContext
->m_eglConfig
;
95 bool CWinSystemX11GLESContext::SetWindow(int width
, int height
, bool fullscreen
, const std::string
& output
, int* winstate
)
99 CWinSystemX11::SetWindow(width
, height
, fullscreen
, output
, &newwin
);
102 RefreshGLContext(m_currentOutput
.compare(output
) != 0);
104 CServiceBroker::GetWinSystem()->GetGfxContext().Clear(0);
105 CServiceBroker::GetWinSystem()->GetGfxContext().Flip(true, false);
108 m_windowDirty
= false;
109 m_bIsInternalXrr
= false;
111 if (!m_delayDispReset
)
113 std::unique_lock
<CCriticalSection
> lock(m_resourceSection
);
114 // tell any shared resources
115 for (std::vector
<IDispResource
*>::iterator i
= m_resources
.begin(); i
!= m_resources
.end(); ++i
)
116 (*i
)->OnResetDisplay();
122 bool CWinSystemX11GLESContext::CreateNewWindow(const std::string
& name
, bool fullScreen
, RESOLUTION_INFO
& res
)
124 CLog::Log(LOGINFO
, "CWinSystemX11GLESContext::CreateNewWindow");
125 if (!CWinSystemX11::CreateNewWindow(name
, fullScreen
, res
) || !m_pGLContext
)
128 m_pGLContext
->QueryExtensions();
132 bool CWinSystemX11GLESContext::ResizeWindow(int newWidth
, int newHeight
, int newLeft
, int newTop
)
134 m_newGlContext
= false;
135 CWinSystemX11::ResizeWindow(newWidth
, newHeight
, newLeft
, newTop
);
136 CRenderSystemGLES::ResetRenderSystem(newWidth
, newHeight
);
140 auto& components
= CServiceBroker::GetAppComponents();
141 const auto appSkin
= components
.GetComponent
<CApplicationSkinHandling
>();
142 appSkin
->ReloadSkin();
148 void CWinSystemX11GLESContext::FinishWindowResize(int newWidth
, int newHeight
)
150 m_newGlContext
= false;
151 CWinSystemX11::FinishWindowResize(newWidth
, newHeight
);
152 CRenderSystemGLES::ResetRenderSystem(newWidth
, newHeight
);
156 auto& components
= CServiceBroker::GetAppComponents();
157 const auto appSkin
= components
.GetComponent
<CApplicationSkinHandling
>();
158 appSkin
->ReloadSkin();
162 bool CWinSystemX11GLESContext::SetFullScreen(bool fullScreen
, RESOLUTION_INFO
& res
, bool blankOtherDisplays
)
164 m_newGlContext
= false;
165 CWinSystemX11::SetFullScreen(fullScreen
, res
, blankOtherDisplays
);
166 CRenderSystemGLES::ResetRenderSystem(res
.iWidth
, res
.iHeight
);
170 auto& components
= CServiceBroker::GetAppComponents();
171 const auto appSkin
= components
.GetComponent
<CApplicationSkinHandling
>();
172 appSkin
->ReloadSkin();
178 bool CWinSystemX11GLESContext::DestroyWindowSystem()
181 m_pGLContext
->Destroy();
182 return CWinSystemX11::DestroyWindowSystem();
185 bool CWinSystemX11GLESContext::DestroyWindow()
188 m_pGLContext
->Detach();
189 return CWinSystemX11::DestroyWindow();
192 XVisualInfo
* CWinSystemX11GLESContext::GetVisual()
194 EGLDisplay eglDisplay
;
196 PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT
=
197 reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC
>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
198 if (eglGetPlatformDisplayEXT
)
202 EGL_PLATFORM_X11_SCREEN_EXT
, m_screen
,
205 eglDisplay
= eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT
,static_cast<EGLNativeDisplayType
>(m_dpy
), attribs
);
208 eglDisplay
= eglGetDisplay(static_cast<EGLNativeDisplayType
>(m_dpy
));
210 if (eglDisplay
== EGL_NO_DISPLAY
)
212 CLog::Log(LOGERROR
, "failed to get egl display");
215 if (!eglInitialize(eglDisplay
, nullptr, nullptr))
217 CLog::Log(LOGERROR
, "failed to initialize egl display");
229 EGL_RENDERABLE_TYPE
, EGL_OPENGL_ES2_BIT
,
233 EGLConfig eglConfig
= 0;
234 if (!eglChooseConfig(eglDisplay
, att
, &eglConfig
, 1, &numConfigs
) || numConfigs
== 0)
236 CLog::Log(LOGERROR
, "Failed to choose a config {}", eglGetError());
240 XVisualInfo x11_visual_info_template
;
241 memset(&x11_visual_info_template
, 0, sizeof(XVisualInfo
));
243 if (!eglGetConfigAttrib(eglDisplay
, eglConfig
,
244 EGL_NATIVE_VISUAL_ID
, reinterpret_cast<EGLint
*>(&x11_visual_info_template
.visualid
)))
246 CLog::Log(LOGERROR
, "Failed to query native visual id");
250 XVisualInfo
* visual
=
251 XGetVisualInfo(m_dpy
, VisualIDMask
, &x11_visual_info_template
, &num_visuals
);
255 bool CWinSystemX11GLESContext::RefreshGLContext(bool force
)
257 bool success
= false;
260 success
= m_pGLContext
->Refresh(force
, m_screen
, m_glWindow
, m_newGlContext
);
263 success
= m_pGLContext
->CreatePB();
264 m_newGlContext
= true;
269 m_dpms
= std::make_shared
<CX11DPMSSupport
>();
270 VIDEOPLAYER::CProcessInfoX11::Register();
271 RETRO::CRPProcessInfoX11::Register();
272 RETRO::CRPProcessInfoX11::RegisterRendererFactory(new RETRO::CRendererFactoryOpenGLES
);
273 CDVDFactoryCodec::ClearHWAccels();
274 VIDEOPLAYER::CRendererFactory::ClearRenderer();
275 CLinuxRendererGLES::Register();
277 std::string gli
= (getenv("KODI_GL_INTERFACE") != nullptr) ? getenv("KODI_GL_INTERFACE") : "";
279 m_pGLContext
= new CGLContextEGL(m_dpy
, EGL_OPENGL_ES_API
);
280 success
= m_pGLContext
->Refresh(force
, m_screen
, m_glWindow
, m_newGlContext
);
281 if (!success
&& gli
== "EGL_PB")
283 success
= m_pGLContext
->CreatePB();
284 m_newGlContext
= true;
290 m_pGLContext
= nullptr;