diff options
Diffstat (limited to 'xbmc/windowing/wayland/WinSystemWaylandEGLContext.cpp')
-rw-r--r-- | xbmc/windowing/wayland/WinSystemWaylandEGLContext.cpp | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/xbmc/windowing/wayland/WinSystemWaylandEGLContext.cpp b/xbmc/windowing/wayland/WinSystemWaylandEGLContext.cpp new file mode 100644 index 0000000..a32cd14 --- /dev/null +++ b/xbmc/windowing/wayland/WinSystemWaylandEGLContext.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2017-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 "WinSystemWaylandEGLContext.h" + +#include "Connection.h" +#include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h" +#include "cores/VideoPlayer/VideoRenderers/RenderFactory.h" +#include "utils/log.h" +#include "windowing/GraphicContext.h" + +#include <EGL/eglext.h> + +using namespace KODI::WINDOWING::WAYLAND; +using namespace KODI::WINDOWING::LINUX; + +CWinSystemWaylandEGLContext::CWinSystemWaylandEGLContext() + : CWinSystemEGL{EGL_PLATFORM_WAYLAND_EXT, "EGL_EXT_platform_wayland"} +{} + +bool CWinSystemWaylandEGLContext::InitWindowSystemEGL(EGLint renderableType, EGLint apiType) +{ + VIDEOPLAYER::CRendererFactory::ClearRenderer(); + CDVDFactoryCodec::ClearHWAccels(); + + if (!CWinSystemWayland::InitWindowSystem()) + { + return false; + } + + if (!m_eglContext.CreatePlatformDisplay(GetConnection()->GetDisplay(), GetConnection()->GetDisplay())) + { + return false; + } + + if (!m_eglContext.InitializeDisplay(apiType)) + { + return false; + } + + if (!m_eglContext.ChooseConfig(renderableType)) + { + return false; + } + + return true; +} + +bool CWinSystemWaylandEGLContext::CreateNewWindow(const std::string& name, + bool fullScreen, + RESOLUTION_INFO& res) +{ + if (!CWinSystemWayland::CreateNewWindow(name, fullScreen, res)) + { + return false; + } + + if (!CreateContext()) + { + return false; + } + + m_nativeWindow = wayland::egl_window_t{GetMainSurface(), GetBufferSize().Width(), GetBufferSize().Height()}; + + // CWinSystemWayland::CreateNewWindow sets internal m_bufferSize + // to the resolution that should be used for the initial surface size + // - the compositor might want something other than the resolution given + if (!m_eglContext.CreatePlatformSurface( + m_nativeWindow.c_ptr(), reinterpret_cast<khronos_uintptr_t>(m_nativeWindow.c_ptr()))) + { + return false; + } + + if (!m_eglContext.BindContext()) + { + return false; + } + + // Never enable the vsync of the EGL implementation, we handle that ourselves + // in WinSystemWayland + m_eglContext.SetVSync(false); + + return true; +} + +bool CWinSystemWaylandEGLContext::DestroyWindow() +{ + m_eglContext.DestroySurface(); + m_nativeWindow = {}; + + return CWinSystemWayland::DestroyWindow(); +} + +bool CWinSystemWaylandEGLContext::DestroyWindowSystem() +{ + m_eglContext.Destroy(); + + return CWinSystemWayland::DestroyWindowSystem(); +} + +CSizeInt CWinSystemWaylandEGLContext::GetNativeWindowAttachedSize() +{ + int width, height; + m_nativeWindow.get_attached_size(width, height); + return {width, height}; +} + +void CWinSystemWaylandEGLContext::SetContextSize(CSizeInt size) +{ + // Change EGL surface size if necessary + if (GetNativeWindowAttachedSize() != size) + { + CLog::LogF(LOGDEBUG, "Updating egl_window size to {}x{}", size.Width(), size.Height()); + m_nativeWindow.resize(size.Width(), size.Height(), 0, 0); + } +} + +void CWinSystemWaylandEGLContext::PresentFrame(bool rendered) +{ + PrepareFramePresentation(); + + if (rendered) + { + if (!m_eglContext.TrySwapBuffers()) + { + // For now we just hard fail if this fails + // Theoretically, EGL_CONTEXT_LOST could be handled, but it needs to be checked + // whether egl implementations actually use it (mesa does not) + CEGLUtils::Log(LOGERROR, "eglSwapBuffers failed"); + throw std::runtime_error("eglSwapBuffers failed"); + } + // eglSwapBuffers() (hopefully) calls commit on the surface and flushes + // ... well mesa does anyway + } + else + { + // For presentation feedback: Get notification of the next vblank even + // when contents did not change + GetMainSurface().commit(); + // Make sure it reaches the compositor + GetConnection()->GetDisplay().flush(); + } + + FinishFramePresentation(); +} |