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::BindTextureUploadContext()
98 return static_cast<CGLContextEGL
*>(m_pGLContext
)->BindTextureUploadContext();
103 bool CWinSystemX11GLESContext::UnbindTextureUploadContext()
106 return static_cast<CGLContextEGL
*>(m_pGLContext
)->UnbindTextureUploadContext();
111 bool CWinSystemX11GLESContext::HasContext()
114 return static_cast<CGLContextEGL
*>(m_pGLContext
)->HasContext();
119 bool CWinSystemX11GLESContext::SetWindow(int width
, int height
, bool fullscreen
, const std::string
& output
, int* winstate
)
123 CWinSystemX11::SetWindow(width
, height
, fullscreen
, output
, &newwin
);
126 RefreshGLContext(m_currentOutput
.compare(output
) != 0);
128 CServiceBroker::GetWinSystem()->GetGfxContext().Clear(0);
129 CServiceBroker::GetWinSystem()->GetGfxContext().Flip(true, false);
132 m_windowDirty
= false;
133 m_bIsInternalXrr
= false;
135 if (!m_delayDispReset
)
137 std::unique_lock
<CCriticalSection
> lock(m_resourceSection
);
138 // tell any shared resources
139 for (std::vector
<IDispResource
*>::iterator i
= m_resources
.begin(); i
!= m_resources
.end(); ++i
)
140 (*i
)->OnResetDisplay();
146 bool CWinSystemX11GLESContext::CreateNewWindow(const std::string
& name
, bool fullScreen
, RESOLUTION_INFO
& res
)
148 CLog::Log(LOGINFO
, "CWinSystemX11GLESContext::CreateNewWindow");
149 if (!CWinSystemX11::CreateNewWindow(name
, fullScreen
, res
) || !m_pGLContext
)
152 m_pGLContext
->QueryExtensions();
156 bool CWinSystemX11GLESContext::ResizeWindow(int newWidth
, int newHeight
, int newLeft
, int newTop
)
158 m_newGlContext
= false;
159 CWinSystemX11::ResizeWindow(newWidth
, newHeight
, newLeft
, newTop
);
160 CRenderSystemGLES::ResetRenderSystem(newWidth
, newHeight
);
164 auto& components
= CServiceBroker::GetAppComponents();
165 const auto appSkin
= components
.GetComponent
<CApplicationSkinHandling
>();
166 appSkin
->ReloadSkin();
172 void CWinSystemX11GLESContext::FinishWindowResize(int newWidth
, int newHeight
)
174 m_newGlContext
= false;
175 CWinSystemX11::FinishWindowResize(newWidth
, newHeight
);
176 CRenderSystemGLES::ResetRenderSystem(newWidth
, newHeight
);
180 auto& components
= CServiceBroker::GetAppComponents();
181 const auto appSkin
= components
.GetComponent
<CApplicationSkinHandling
>();
182 appSkin
->ReloadSkin();
186 bool CWinSystemX11GLESContext::SetFullScreen(bool fullScreen
, RESOLUTION_INFO
& res
, bool blankOtherDisplays
)
188 m_newGlContext
= false;
189 CWinSystemX11::SetFullScreen(fullScreen
, res
, blankOtherDisplays
);
190 CRenderSystemGLES::ResetRenderSystem(res
.iWidth
, res
.iHeight
);
194 auto& components
= CServiceBroker::GetAppComponents();
195 const auto appSkin
= components
.GetComponent
<CApplicationSkinHandling
>();
196 appSkin
->ReloadSkin();
202 bool CWinSystemX11GLESContext::DestroyWindowSystem()
205 m_pGLContext
->Destroy();
206 return CWinSystemX11::DestroyWindowSystem();
209 bool CWinSystemX11GLESContext::DestroyWindow()
212 m_pGLContext
->Detach();
213 return CWinSystemX11::DestroyWindow();
216 XVisualInfo
* CWinSystemX11GLESContext::GetVisual()
218 EGLDisplay eglDisplay
;
220 PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT
=
221 reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC
>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
222 if (eglGetPlatformDisplayEXT
)
226 EGL_PLATFORM_X11_SCREEN_EXT
, m_screen
,
229 eglDisplay
= eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT
,static_cast<EGLNativeDisplayType
>(m_dpy
), attribs
);
232 eglDisplay
= eglGetDisplay(static_cast<EGLNativeDisplayType
>(m_dpy
));
234 if (eglDisplay
== EGL_NO_DISPLAY
)
236 CLog::Log(LOGERROR
, "failed to get egl display");
239 if (!eglInitialize(eglDisplay
, nullptr, nullptr))
241 CLog::Log(LOGERROR
, "failed to initialize egl display");
253 EGL_RENDERABLE_TYPE
, EGL_OPENGL_ES2_BIT
,
257 EGLConfig eglConfig
= 0;
258 if (!eglChooseConfig(eglDisplay
, att
, &eglConfig
, 1, &numConfigs
) || numConfigs
== 0)
260 CLog::Log(LOGERROR
, "Failed to choose a config {}", eglGetError());
264 XVisualInfo x11_visual_info_template
;
265 memset(&x11_visual_info_template
, 0, sizeof(XVisualInfo
));
267 if (!eglGetConfigAttrib(eglDisplay
, eglConfig
,
268 EGL_NATIVE_VISUAL_ID
, reinterpret_cast<EGLint
*>(&x11_visual_info_template
.visualid
)))
270 CLog::Log(LOGERROR
, "Failed to query native visual id");
274 XVisualInfo
* visual
=
275 XGetVisualInfo(m_dpy
, VisualIDMask
, &x11_visual_info_template
, &num_visuals
);
279 bool CWinSystemX11GLESContext::RefreshGLContext(bool force
)
281 bool success
= false;
284 success
= m_pGLContext
->Refresh(force
, m_screen
, m_glWindow
, m_newGlContext
);
287 success
= m_pGLContext
->CreatePB();
288 m_newGlContext
= true;
293 m_dpms
= std::make_shared
<CX11DPMSSupport
>();
294 VIDEOPLAYER::CProcessInfoX11::Register();
295 RETRO::CRPProcessInfoX11::Register();
296 RETRO::CRPProcessInfoX11::RegisterRendererFactory(new RETRO::CRendererFactoryOpenGLES
);
297 CDVDFactoryCodec::ClearHWAccels();
298 VIDEOPLAYER::CRendererFactory::ClearRenderer();
299 CLinuxRendererGLES::Register();
301 std::string gli
= (getenv("KODI_GL_INTERFACE") != nullptr) ? getenv("KODI_GL_INTERFACE") : "";
303 m_pGLContext
= new CGLContextEGL(m_dpy
, EGL_OPENGL_ES_API
);
304 success
= m_pGLContext
->Refresh(force
, m_screen
, m_glWindow
, m_newGlContext
);
305 if (!success
&& gli
== "EGL_PB")
307 success
= m_pGLContext
->CreatePB();
308 m_newGlContext
= true;
314 m_pGLContext
= nullptr;