diff options
Diffstat (limited to 'xbmc/windowing/X11/WinSystemX11GLESContext.cpp')
-rw-r--r-- | xbmc/windowing/X11/WinSystemX11GLESContext.cpp | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/xbmc/windowing/X11/WinSystemX11GLESContext.cpp b/xbmc/windowing/X11/WinSystemX11GLESContext.cpp new file mode 100644 index 0000000..e2367d3 --- /dev/null +++ b/xbmc/windowing/X11/WinSystemX11GLESContext.cpp @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2005-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "WinSystemX11GLESContext.h" + +#include "GLContextEGL.h" +#include "OptionalsReg.h" +#include "X11DPMSSupport.h" +#include "application/ApplicationComponents.h" +#include "application/ApplicationSkinHandling.h" +#include "cores/RetroPlayer/process/X11/RPProcessInfoX11.h" +#include "cores/RetroPlayer/rendering/VideoRenderers/RPRendererOpenGLES.h" +#include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h" +#include "cores/VideoPlayer/Process/X11/ProcessInfoX11.h" +#include "cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h" +#include "cores/VideoPlayer/VideoRenderers/RenderFactory.h" +#include "guilib/DispResource.h" +#include "utils/log.h" +#include "windowing/GraphicContext.h" +#include "windowing/WindowSystemFactory.h" + +#include <mutex> + +using namespace KODI; +using namespace KODI::WINDOWING::X11; + +void CWinSystemX11GLESContext::Register() +{ + KODI::WINDOWING::CWindowSystemFactory::RegisterWindowSystem(CreateWinSystem, "x11"); +} + +std::unique_ptr<CWinSystemBase> CWinSystemX11GLESContext::CreateWinSystem() +{ + return std::make_unique<CWinSystemX11GLESContext>(); +} + +CWinSystemX11GLESContext::~CWinSystemX11GLESContext() +{ + delete m_pGLContext; +} + +void CWinSystemX11GLESContext::PresentRenderImpl(bool rendered) +{ + if (rendered && m_pGLContext) + m_pGLContext->SwapBuffers(); + + if (m_delayDispReset && m_dispResetTimer.IsTimePast()) + { + m_delayDispReset = false; + std::unique_lock<CCriticalSection> lock(m_resourceSection); + // tell any shared resources + for (std::vector<IDispResource*>::iterator i = m_resources.begin(); i != m_resources.end(); ++i) + (*i)->OnResetDisplay(); + } +} + +void CWinSystemX11GLESContext::SetVSyncImpl(bool enable) +{ + m_pGLContext->SetVSync(enable); +} + +bool CWinSystemX11GLESContext::IsExtSupported(const char* extension) const +{ + if (strncmp(extension, m_pGLContext->ExtPrefix().c_str(), 4) != 0) + return CRenderSystemGLES::IsExtSupported(extension); + + return m_pGLContext->IsExtSupported(extension); +} + +EGLDisplay CWinSystemX11GLESContext::GetEGLDisplay() const +{ + return m_pGLContext->m_eglDisplay; +} + +EGLSurface CWinSystemX11GLESContext::GetEGLSurface() const +{ + return m_pGLContext->m_eglSurface; +} + +EGLContext CWinSystemX11GLESContext::GetEGLContext() const +{ + return m_pGLContext->m_eglContext; +} + +EGLConfig CWinSystemX11GLESContext::GetEGLConfig() const +{ + return m_pGLContext->m_eglConfig; +} + +bool CWinSystemX11GLESContext::SetWindow(int width, int height, bool fullscreen, const std::string& output, int* winstate) +{ + int newwin = 0; + + CWinSystemX11::SetWindow(width, height, fullscreen, output, &newwin); + if (newwin) + { + RefreshGLContext(m_currentOutput.compare(output) != 0); + XSync(m_dpy, false); + CServiceBroker::GetWinSystem()->GetGfxContext().Clear(0); + CServiceBroker::GetWinSystem()->GetGfxContext().Flip(true, false); + ResetVSync(); + + m_windowDirty = false; + m_bIsInternalXrr = false; + + if (!m_delayDispReset) + { + std::unique_lock<CCriticalSection> lock(m_resourceSection); + // tell any shared resources + for (std::vector<IDispResource*>::iterator i = m_resources.begin(); i != m_resources.end(); ++i) + (*i)->OnResetDisplay(); + } + } + return true; +} + +bool CWinSystemX11GLESContext::CreateNewWindow(const std::string& name, bool fullScreen, RESOLUTION_INFO& res) +{ + CLog::Log(LOGINFO, "CWinSystemX11GLESContext::CreateNewWindow"); + if (!CWinSystemX11::CreateNewWindow(name, fullScreen, res) || !m_pGLContext) + return false; + + m_pGLContext->QueryExtensions(); + return true; +} + +bool CWinSystemX11GLESContext::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop) +{ + m_newGlContext = false; + CWinSystemX11::ResizeWindow(newWidth, newHeight, newLeft, newTop); + CRenderSystemGLES::ResetRenderSystem(newWidth, newHeight); + + if (m_newGlContext) + { + auto& components = CServiceBroker::GetAppComponents(); + const auto appSkin = components.GetComponent<CApplicationSkinHandling>(); + appSkin->ReloadSkin(); + } + + return true; +} + +void CWinSystemX11GLESContext::FinishWindowResize(int newWidth, int newHeight) +{ + m_newGlContext = false; + CWinSystemX11::FinishWindowResize(newWidth, newHeight); + CRenderSystemGLES::ResetRenderSystem(newWidth, newHeight); + + if (m_newGlContext) + { + auto& components = CServiceBroker::GetAppComponents(); + const auto appSkin = components.GetComponent<CApplicationSkinHandling>(); + appSkin->ReloadSkin(); + } +} + +bool CWinSystemX11GLESContext::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) +{ + m_newGlContext = false; + CWinSystemX11::SetFullScreen(fullScreen, res, blankOtherDisplays); + CRenderSystemGLES::ResetRenderSystem(res.iWidth, res.iHeight); + + if (m_newGlContext) + { + auto& components = CServiceBroker::GetAppComponents(); + const auto appSkin = components.GetComponent<CApplicationSkinHandling>(); + appSkin->ReloadSkin(); + } + + return true; +} + +bool CWinSystemX11GLESContext::DestroyWindowSystem() +{ + if (m_pGLContext) + m_pGLContext->Destroy(); + return CWinSystemX11::DestroyWindowSystem(); +} + +bool CWinSystemX11GLESContext::DestroyWindow() +{ + if (m_pGLContext) + m_pGLContext->Detach(); + return CWinSystemX11::DestroyWindow(); +} + +XVisualInfo* CWinSystemX11GLESContext::GetVisual() +{ + EGLDisplay eglDisplay; + + PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = + reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT")); + if (eglGetPlatformDisplayEXT) + { + EGLint attribs[] = + { + EGL_PLATFORM_X11_SCREEN_EXT, m_screen, + EGL_NONE + }; + eglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT,static_cast<EGLNativeDisplayType>(m_dpy), attribs); + } + else + eglDisplay = eglGetDisplay(static_cast<EGLNativeDisplayType>(m_dpy)); + + if (eglDisplay == EGL_NO_DISPLAY) + { + CLog::Log(LOGERROR, "failed to get egl display"); + return nullptr; + } + if (!eglInitialize(eglDisplay, nullptr, nullptr)) + { + CLog::Log(LOGERROR, "failed to initialize egl display"); + return nullptr; + } + + GLint att[] = + { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_BUFFER_SIZE, 32, + EGL_DEPTH_SIZE, 24, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + EGLint numConfigs; + EGLConfig eglConfig = 0; + if (!eglChooseConfig(eglDisplay, att, &eglConfig, 1, &numConfigs) || numConfigs == 0) + { + CLog::Log(LOGERROR, "Failed to choose a config {}", eglGetError()); + return nullptr; + } + + XVisualInfo x11_visual_info_template; + memset(&x11_visual_info_template, 0, sizeof(XVisualInfo)); + + if (!eglGetConfigAttrib(eglDisplay, eglConfig, + EGL_NATIVE_VISUAL_ID, reinterpret_cast<EGLint*>(&x11_visual_info_template.visualid))) + { + CLog::Log(LOGERROR, "Failed to query native visual id"); + return nullptr; + } + int num_visuals; + XVisualInfo* visual = + XGetVisualInfo(m_dpy, VisualIDMask, &x11_visual_info_template, &num_visuals); + return visual; +} + +bool CWinSystemX11GLESContext::RefreshGLContext(bool force) +{ + bool success = false; + if (m_pGLContext) + { + success = m_pGLContext->Refresh(force, m_screen, m_glWindow, m_newGlContext); + if (!success) + { + success = m_pGLContext->CreatePB(); + m_newGlContext = true; + } + return success; + } + + m_dpms = std::make_shared<CX11DPMSSupport>(); + VIDEOPLAYER::CProcessInfoX11::Register(); + RETRO::CRPProcessInfoX11::Register(); + RETRO::CRPProcessInfoX11::RegisterRendererFactory(new RETRO::CRendererFactoryOpenGLES); + CDVDFactoryCodec::ClearHWAccels(); + VIDEOPLAYER::CRendererFactory::ClearRenderer(); + CLinuxRendererGLES::Register(); + + std::string gli = (getenv("KODI_GL_INTERFACE") != nullptr) ? getenv("KODI_GL_INTERFACE") : ""; + + m_pGLContext = new CGLContextEGL(m_dpy, EGL_OPENGL_ES_API); + success = m_pGLContext->Refresh(force, m_screen, m_glWindow, m_newGlContext); + if (!success && gli == "EGL_PB") + { + success = m_pGLContext->CreatePB(); + m_newGlContext = true; + } + + if (!success) + { + delete m_pGLContext; + m_pGLContext = nullptr; + } + return success; +} |