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 "WinSystemX11GLContext.h"
11 #include "GLContextEGL.h"
12 #include "OptionalsReg.h"
13 #include "ServiceBroker.h"
14 #include "VideoSyncOML.h"
15 #include "X11DPMSSupport.h"
16 #include "application/AppParams.h"
17 #include "application/ApplicationComponents.h"
18 #include "application/ApplicationSkinHandling.h"
19 #include "cores/RetroPlayer/process/X11/RPProcessInfoX11.h"
20 #include "cores/RetroPlayer/rendering/VideoRenderers/RPRendererOpenGL.h"
21 #include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h"
22 #include "cores/VideoPlayer/Process/X11/ProcessInfoX11.h"
23 #include "cores/VideoPlayer/VideoReferenceClock.h"
24 #include "cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h"
25 #include "cores/VideoPlayer/VideoRenderers/RenderFactory.h"
26 #include "guilib/DispResource.h"
27 #include "rendering/gl/ScreenshotSurfaceGL.h"
28 #include "windowing/GraphicContext.h"
29 #include "windowing/WindowSystemFactory.h"
36 #include <X11/Xutil.h>
39 using namespace KODI::WINDOWING::X11
;
42 void CWinSystemX11GLContext::Register()
44 KODI::WINDOWING::CWindowSystemFactory::RegisterWindowSystem(CreateWinSystem
, "x11");
47 std::unique_ptr
<CWinSystemBase
> CWinSystemX11GLContext::CreateWinSystem()
49 return std::make_unique
<CWinSystemX11GLContext
>();
52 CWinSystemX11GLContext::~CWinSystemX11GLContext()
57 void CWinSystemX11GLContext::PresentRenderImpl(bool rendered
)
60 m_pGLContext
->SwapBuffers();
62 if (m_delayDispReset
&& m_dispResetTimer
.IsTimePast())
64 m_delayDispReset
= false;
65 std::unique_lock
<CCriticalSection
> lock(m_resourceSection
);
66 // tell any shared resources
67 for (std::vector
<IDispResource
*>::iterator i
= m_resources
.begin(); i
!= m_resources
.end(); ++i
)
68 (*i
)->OnResetDisplay();
72 void CWinSystemX11GLContext::SetVSyncImpl(bool enable
)
74 m_pGLContext
->SetVSync(enable
);
77 bool CWinSystemX11GLContext::IsExtSupported(const char* extension
) const
79 if(strncmp(extension
, m_pGLContext
->ExtPrefix().c_str(), 4) != 0)
80 return CRenderSystemGL::IsExtSupported(extension
);
82 return m_pGLContext
->IsExtSupported(extension
);
85 XID
CWinSystemX11GLContext::GetWindow() const
87 return GLXGetWindow(m_pGLContext
);
90 void* CWinSystemX11GLContext::GetGlxContext() const
92 return GLXGetContext(m_pGLContext
);
95 EGLDisplay
CWinSystemX11GLContext::GetEGLDisplay() const
97 return static_cast<CGLContextEGL
*>(m_pGLContext
)->m_eglDisplay
;
100 EGLSurface
CWinSystemX11GLContext::GetEGLSurface() const
102 return static_cast<CGLContextEGL
*>(m_pGLContext
)->m_eglSurface
;
105 EGLContext
CWinSystemX11GLContext::GetEGLContext() const
107 return static_cast<CGLContextEGL
*>(m_pGLContext
)->m_eglContext
;
110 EGLConfig
CWinSystemX11GLContext::GetEGLConfig() const
112 return static_cast<CGLContextEGL
*>(m_pGLContext
)->m_eglConfig
;
115 bool CWinSystemX11GLContext::BindTextureUploadContext()
118 return static_cast<CGLContextEGL
*>(m_pGLContext
)->BindTextureUploadContext();
123 bool CWinSystemX11GLContext::UnbindTextureUploadContext()
126 return static_cast<CGLContextEGL
*>(m_pGLContext
)->UnbindTextureUploadContext();
131 bool CWinSystemX11GLContext::HasContext()
134 return static_cast<CGLContextEGL
*>(m_pGLContext
)->HasContext();
139 bool CWinSystemX11GLContext::SetWindow(int width
, int height
, bool fullscreen
, const std::string
&output
, int *winstate
)
143 CWinSystemX11::SetWindow(width
, height
, fullscreen
, output
, &newwin
);
146 RefreshGLContext(m_currentOutput
.compare(output
) != 0);
148 CServiceBroker::GetWinSystem()->GetGfxContext().Clear(0);
149 CServiceBroker::GetWinSystem()->GetGfxContext().Flip(true, false);
152 m_windowDirty
= false;
153 m_bIsInternalXrr
= false;
155 if (!m_delayDispReset
)
157 std::unique_lock
<CCriticalSection
> lock(m_resourceSection
);
158 // tell any shared resources
159 for (std::vector
<IDispResource
*>::iterator i
= m_resources
.begin(); i
!= m_resources
.end(); ++i
)
160 (*i
)->OnResetDisplay();
166 bool CWinSystemX11GLContext::CreateNewWindow(const std::string
& name
, bool fullScreen
, RESOLUTION_INFO
& res
)
168 if(!CWinSystemX11::CreateNewWindow(name
, fullScreen
, res
))
171 m_pGLContext
->QueryExtensions();
172 m_bufferAgeSupport
= m_pGLContext
->IsBufferAgeSupported();
176 bool CWinSystemX11GLContext::ResizeWindow(int newWidth
, int newHeight
, int newLeft
, int newTop
)
178 m_newGlContext
= false;
179 CWinSystemX11::ResizeWindow(newWidth
, newHeight
, newLeft
, newTop
);
180 CRenderSystemGL::ResetRenderSystem(newWidth
, newHeight
);
184 auto& components
= CServiceBroker::GetAppComponents();
185 const auto appSkin
= components
.GetComponent
<CApplicationSkinHandling
>();
186 appSkin
->ReloadSkin();
192 void CWinSystemX11GLContext::FinishWindowResize(int newWidth
, int newHeight
)
194 m_newGlContext
= false;
195 CWinSystemX11::FinishWindowResize(newWidth
, newHeight
);
196 CRenderSystemGL::ResetRenderSystem(newWidth
, newHeight
);
200 auto& components
= CServiceBroker::GetAppComponents();
201 const auto appSkin
= components
.GetComponent
<CApplicationSkinHandling
>();
202 appSkin
->ReloadSkin();
206 bool CWinSystemX11GLContext::SetFullScreen(bool fullScreen
, RESOLUTION_INFO
& res
, bool blankOtherDisplays
)
208 m_newGlContext
= false;
209 CWinSystemX11::SetFullScreen(fullScreen
, res
, blankOtherDisplays
);
210 CRenderSystemGL::ResetRenderSystem(res
.iWidth
, res
.iHeight
);
214 auto& components
= CServiceBroker::GetAppComponents();
215 const auto appSkin
= components
.GetComponent
<CApplicationSkinHandling
>();
216 appSkin
->ReloadSkin();
222 bool CWinSystemX11GLContext::DestroyWindowSystem()
225 m_pGLContext
->Destroy();
226 return CWinSystemX11::DestroyWindowSystem();
229 bool CWinSystemX11GLContext::DestroyWindow()
232 m_pGLContext
->Detach();
233 return CWinSystemX11::DestroyWindow();
236 XVisualInfo
* CWinSystemX11GLContext::GetVisual()
239 XVisualInfo vTemplate
;
240 XVisualInfo
*visual
= nullptr;
242 int vMask
= VisualScreenMask
| VisualDepthMask
| VisualClassMask
;
244 vTemplate
.screen
= m_screen
;
245 vTemplate
.depth
= 24;
246 vTemplate
.c_class
= TrueColor
;
248 visual
= XGetVisualInfo(m_dpy
, vMask
, &vTemplate
, &count
);
252 vTemplate
.depth
= 30;
253 visual
= XGetVisualInfo(m_dpy
, vMask
, &vTemplate
, &count
);
259 bool CWinSystemX11GLContext::RefreshGLContext(bool force
)
261 bool success
= false;
266 auto& components
= CServiceBroker::GetAppComponents();
267 const auto appSkin
= components
.GetComponent
<CApplicationSkinHandling
>();
268 appSkin
->UnloadSkin();
269 CRenderSystemGL::DestroyRenderSystem();
271 success
= m_pGLContext
->Refresh(force
, m_screen
, m_glWindow
, m_newGlContext
);
274 success
= m_pGLContext
->CreatePB();
275 m_newGlContext
= true;
278 CRenderSystemGL::InitRenderSystem();
282 m_dpms
= std::make_shared
<CX11DPMSSupport
>();
283 VIDEOPLAYER::CProcessInfoX11::Register();
284 RETRO::CRPProcessInfoX11::Register();
285 RETRO::CRPProcessInfoX11::RegisterRendererFactory(new RETRO::CRendererFactoryOpenGL
);
286 CDVDFactoryCodec::ClearHWAccels();
287 VIDEOPLAYER::CRendererFactory::ClearRenderer();
288 CLinuxRendererGL::Register();
290 CScreenshotSurfaceGL::Register();
292 std::string gpuvendor
;
293 const char* vend
= (const char*) glGetString(GL_VENDOR
);
296 std::transform(gpuvendor
.begin(), gpuvendor
.end(), gpuvendor
.begin(), ::tolower
);
297 bool isNvidia
= (gpuvendor
.compare(0, 6, "nvidia") == 0);
298 bool isIntel
= (gpuvendor
.compare(0, 5, "intel") == 0);
300 std::string_view gli
= CServiceBroker::GetAppParams()->GetGlInterface();
304 m_pGLContext
= new CGLContextEGL(m_dpy
, EGL_OPENGL_API
);
305 success
= m_pGLContext
->Refresh(force
, m_screen
, m_glWindow
, m_newGlContext
);
310 m_vaapiProxy
.reset(VaapiProxyCreate());
311 VaapiProxyConfig(m_vaapiProxy
.get(), GetDisplay(),
312 static_cast<CGLContextEGL
*>(m_pGLContext
)->m_eglDisplay
);
313 bool general
= false;
314 bool deepColor
= false;
315 VAAPIRegisterRenderGL(m_vaapiProxy
.get(), general
, deepColor
);
318 VAAPIRegister(m_vaapiProxy
.get(), deepColor
);
321 if (isIntel
|| gli
== "egl")
325 else if (gli
== "egl-pb")
327 success
= m_pGLContext
->CreatePB();
335 // fallback for vdpau
336 m_pGLContext
= GLXContextCreate(m_dpy
);
337 success
= m_pGLContext
->Refresh(force
, m_screen
, m_glWindow
, m_newGlContext
);
341 VDPAURegisterRender();
346 std::unique_ptr
<CVideoSync
> CWinSystemX11GLContext::GetVideoSync(CVideoReferenceClock
* clock
)
348 std::unique_ptr
<CVideoSync
> pVSync
;
350 if (dynamic_cast<CGLContextEGL
*>(m_pGLContext
))
352 pVSync
= std::make_unique
<CVideoSyncOML
>(clock
, *this);
356 pVSync
.reset(GLXVideoSyncCreate(clock
, *this));
362 float CWinSystemX11GLContext::GetFrameLatencyAdjustment()
366 uint64_t msc
, interval
;
367 float micros
= m_pGLContext
->GetVblankTiming(msc
, interval
);
368 return micros
/ 1000;
373 uint64_t CWinSystemX11GLContext::GetVblankTiming(uint64_t &msc
, uint64_t &interval
)
377 float micros
= m_pGLContext
->GetVblankTiming(msc
, interval
);
385 void CWinSystemX11GLContext::delete_CVaapiProxy::operator()(CVaapiProxy
*p
) const