Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wayland Support #11257

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions CMake/FindWaylandProtocols.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# from https://github.com/glfw/glfw/blob/master/CMake/modules/FindWaylandProtocols.cmake

find_package(PkgConfig)

pkg_check_modules(WaylandProtocols QUIET wayland-protocols>=${WaylandProtocols_FIND_VERSION})

execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-protocols
OUTPUT_VARIABLE WaylandProtocols_PKGDATADIR
RESULT_VARIABLE _pkgconfig_failed)
if (_pkgconfig_failed)
message(FATAL_ERROR "Missing wayland-protocols pkgdatadir")
endif()

string(REGEX REPLACE "[\r\n]" "" WaylandProtocols_PKGDATADIR "${WaylandProtocols_PKGDATADIR}")

find_package_handle_standard_args(WaylandProtocols
FOUND_VAR
WaylandProtocols_FOUND
REQUIRED_VARS
WaylandProtocols_PKGDATADIR
VERSION_VAR
WaylandProtocols_VERSION
HANDLE_COMPONENTS
)

set(WAYLAND_PROTOCOLS_FOUND ${WaylandProtocols_FOUND})
set(WAYLAND_PROTOCOLS_PKGDATADIR ${WaylandProtocols_PKGDATADIR})
set(WAYLAND_PROTOCOLS_VERSION ${WaylandProtocols_VERSION})

34 changes: 34 additions & 0 deletions CMake/FindXKBCommon.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# - Try to find XKBCommon
# Once done, this will define
#
# XKBCOMMON_FOUND - System has XKBCommon
# XKBCOMMON_INCLUDE_DIRS - The XKBCommon include directories
# XKBCOMMON_LIBRARIES - The libraries needed to use XKBCommon
# XKBCOMMON_DEFINITIONS - Compiler switches required for using XKBCommon

find_package(PkgConfig)
pkg_check_modules(PC_XKBCOMMON QUIET xkbcommon)
set(XKBCOMMON_DEFINITIONS ${PC_XKBCOMMON_CFLAGS_OTHER})

find_path(XKBCOMMON_INCLUDE_DIR
NAMES xkbcommon/xkbcommon.h
HINTS ${PC_XKBCOMMON_INCLUDE_DIR} ${PC_XKBCOMMON_INCLUDE_DIRS}
)

find_library(XKBCOMMON_LIBRARY
NAMES xkbcommon
HINTS ${PC_XKBCOMMON_LIBRARY} ${PC_XKBCOMMON_LIBRARY_DIRS}
)

set(XKBCOMMON_LIBRARIES ${XKBCOMMON_LIBRARY})
set(XKBCOMMON_LIBRARY_DIRS ${XKBCOMMON_LIBRARY_DIRS})
set(XKBCOMMON_INCLUDE_DIRS ${XKBCOMMON_INCLUDE_DIR})

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(XKBCommon DEFAULT_MSG
XKBCOMMON_LIBRARY
XKBCOMMON_INCLUDE_DIR
)

mark_as_advanced(XKBCOMMON_LIBRARY XKBCOMMON_INCLUDE_DIR)

12 changes: 12 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ set(DOLPHIN_DEFAULT_UPDATE_TRACK "" CACHE STRING "Name of the default update tra

if(UNIX AND NOT APPLE AND NOT ANDROID)
option(ENABLE_X11 "Enables X11 Support" ON)
option(ENABLE_WAYLAND "Enables Wayland Support" OFF)
endif()
if(NOT WIN32 AND NOT APPLE AND NOT HAIKU)
option(ENABLE_EGL "Enables EGL OpenGL Interface" ON)
Expand Down Expand Up @@ -559,6 +560,17 @@ if(ENABLE_EGL)
endif()
endif()

if(ENABLE_WAYLAND)
find_package(ECM REQUIRED NO_MODULE)
list(APPEND CMAKE_MODULE_PATH "${ECM_MODULE_PATH}")
find_package(Wayland REQUIRED Client Egl)
find_package(WaylandScanner REQUIRED)
find_package(WaylandProtocols 1.15 REQUIRED)
find_package(XKBCommon REQUIRED)
add_definitions(-DHAVE_WAYLAND=1)
message(STATUS "Wayland support enabled")
endif()

if(ENCODE_FRAMEDUMPS)
if(WIN32)
if(_M_X86_64)
Expand Down
7 changes: 5 additions & 2 deletions Source/Android/jni/MainAndroid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,10 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceChang
__android_log_print(ANDROID_LOG_ERROR, DOLPHIN_TAG, "Error: Surface is null.");

if (g_renderer)
g_renderer->ChangeSurface(s_surf);
{
g_renderer->ChangeSurface(s_surf, ANativeWindow_getWidth(s_surf),
ANativeWindow_getHeight(s_surf));
}
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestroyed(JNIEnv*,
Expand All @@ -470,7 +473,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestr
std::lock_guard surface_guard(s_surface_lock);

if (g_renderer)
g_renderer->ChangeSurface(nullptr);
g_renderer->ChangeSurface(nullptr, 0, 0);

if (s_surf)
{
Expand Down
19 changes: 14 additions & 5 deletions Source/Core/Common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -263,11 +263,20 @@ if(ENABLE_EGL AND EGL_FOUND)
GL/GLInterface/EGLAndroid.cpp
GL/GLInterface/EGLAndroid.h
)
elseif(ENABLE_X11 AND X11_FOUND)
target_sources(common PRIVATE
GL/GLInterface/EGLX11.cpp
GL/GLInterface/EGLX11.h
)
else()
if(ENABLE_X11 AND X11_FOUND)
target_sources(common PRIVATE
GL/GLInterface/EGLX11.cpp
GL/GLInterface/EGLX11.h
)
endif()
if(ENABLE_WAYLAND AND WAYLAND_FOUND)
target_sources(common PRIVATE
GL/GLInterface/EGLWayland.cpp
GL/GLInterface/EGLWayland.h
)
target_link_libraries(common PRIVATE Wayland::Egl)
endif()
endif()
target_include_directories(common PRIVATE ${EGL_INCLUDE_DIRS})
target_link_libraries(common PUBLIC ${EGL_LIBRARIES})
Expand Down
11 changes: 9 additions & 2 deletions Source/Core/Common/GL/GLContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
#if defined(ANDROID)
#include "Common/GL/GLInterface/EGLAndroid.h"
#endif
#if HAVE_WAYLAND
#include "Common/GL/GLInterface/EGLWayland.h"
#endif
#endif

const std::array<std::pair<int, int>, 9> GLContext::s_desktop_opengl_versions = {
Expand Down Expand Up @@ -57,11 +60,11 @@ bool GLContext::ClearCurrent()
return false;
}

void GLContext::Update()
void GLContext::UpdateDimensions(int window_width, int window_height)
{
}

void GLContext::UpdateSurface(void* window_handle)
void GLContext::UpdateSurface(void* window_handle, int window_width, int window_height)
{
}

Expand Down Expand Up @@ -113,6 +116,10 @@ std::unique_ptr<GLContext> GLContext::Create(const WindowSystemInfo& wsi, bool s
#endif
}
#endif
#if HAVE_WAYLAND
if (wsi.type == WindowSystemType::Wayland)
context = std::make_unique<GLContextEGLWayland>();
#endif
#if HAVE_EGL
if (wsi.type == WindowSystemType::Headless || wsi.type == WindowSystemType::FBDev)
context = std::make_unique<GLContextEGL>();
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/Common/GL/GLContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ class GLContext
virtual bool MakeCurrent();
virtual bool ClearCurrent();

virtual void Update();
virtual void UpdateSurface(void* window_handle);
virtual void UpdateDimensions(int window_width, int window_height);
virtual void UpdateSurface(void* window_handle, int window_width, int window_height);

virtual void Swap();
virtual void SwapInterval(int interval);
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Common/GL/GLInterface/AGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class GLContextAGL final : public GLContext
bool MakeCurrent() override;
bool ClearCurrent() override;

void Update() override;
void UpdateDimensions(int window_width, int window_height) override;

void Swap() override;
void SwapInterval(int interval) override;
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Common/GL/GLInterface/AGL.mm
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ static bool AttachContextToView(NSOpenGLContext* context, NSView* view, u32* wid
return true;
}

void GLContextAGL::Update()
void GLContextAGL::UpdateDimensions(int window_width, int window_height)
{
if (!m_view)
return;
Expand Down
36 changes: 24 additions & 12 deletions Source/Core/Common/GL/GLInterface/EGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,24 +292,16 @@ bool GLContextEGL::CreateWindowSurface()
{
if (!IsHeadless())
{
EGLNativeWindowType native_window = GetEGLNativeWindow(m_config);
m_egl_surface = eglCreateWindowSurface(m_egl_display, m_config, native_window, nullptr);
m_native_window = GetEGLNativeWindow(m_config);
m_egl_surface = eglCreateWindowSurface(m_egl_display, m_config, m_native_window, nullptr);
if (!m_egl_surface)
{
INFO_LOG_FMT(VIDEO, "Error: eglCreateWindowSurface failed");
return false;
}

// Get dimensions from the surface.
EGLint surface_width = 1, surface_height = 1;
if (!eglQuerySurface(m_egl_display, m_egl_surface, EGL_WIDTH, &surface_width) ||
!eglQuerySurface(m_egl_display, m_egl_surface, EGL_HEIGHT, &surface_height))
{
WARN_LOG_FMT(VIDEO,
"Failed to get surface dimensions via eglQuerySurface. Size may be incorrect.");
}
m_backbuffer_width = static_cast<int>(surface_width);
m_backbuffer_height = static_cast<int>(surface_height);
QueryDimensions();
}
else if (!m_supports_surfaceless)
{
Expand Down Expand Up @@ -347,9 +339,16 @@ bool GLContextEGL::MakeCurrent()
return eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface, m_egl_context);
}

void GLContextEGL::UpdateSurface(void* window_handle)
void GLContextEGL::UpdateDimensions(int window_width, int window_height)
{
QueryDimensions();
}

void GLContextEGL::UpdateSurface(void* window_handle, int window_width, int window_height)
{
m_wsi.render_surface = window_handle;
m_wsi.render_surface_width = window_width;
m_wsi.render_surface_height = window_height;
ClearCurrent();
DestroyWindowSurface();
CreateWindowSurface();
Expand All @@ -376,3 +375,16 @@ void GLContextEGL::DestroyContext()
m_egl_context = EGL_NO_CONTEXT;
m_egl_display = EGL_NO_DISPLAY;
}

void GLContextEGL::QueryDimensions()
{
EGLint surface_width = 1, surface_height = 1;
if (!eglQuerySurface(m_egl_display, m_egl_surface, EGL_WIDTH, &surface_width) ||
!eglQuerySurface(m_egl_display, m_egl_surface, EGL_HEIGHT, &surface_height))
{
WARN_LOG_FMT(VIDEO,
"Failed to get surface dimensions via eglQuerySurface. Size may be incorrect.");
}
m_backbuffer_width = static_cast<u32>(surface_width);
m_backbuffer_height = static_cast<u32>(surface_height);
}
6 changes: 5 additions & 1 deletion Source/Core/Common/GL/GLInterface/EGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ class GLContextEGL : public GLContext
bool MakeCurrent() override;
bool ClearCurrent() override;

void UpdateSurface(void* window_handle) override;
void UpdateDimensions(int window_width, int window_height);
void UpdateSurface(void* window_handle, int window_width, int window_height) override;

void Swap() override;
void SwapInterval(int interval) override;
Expand All @@ -39,9 +40,12 @@ class GLContextEGL : public GLContext
void DestroyWindowSurface();
void DetectMode();
void DestroyContext();
void QueryDimensions();

WindowSystemInfo m_wsi = {};

EGLNativeWindowType m_native_window = {};

EGLConfig m_config;
bool m_supports_surfaceless = false;
std::vector<int> m_attribs;
Expand Down
36 changes: 36 additions & 0 deletions Source/Core/Common/GL/GLInterface/EGLWayland.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include "Common/GL/GLInterface/EGLWayland.h"
#include <wayland-egl.h>

GLContextEGLWayland::~GLContextEGLWayland()
{
if (m_native_window)
wl_egl_window_destroy(reinterpret_cast<wl_egl_window*>(m_native_window));
}

EGLDisplay GLContextEGLWayland::OpenEGLDisplay()
{
return eglGetDisplay(reinterpret_cast<EGLNativeDisplayType>(m_wsi.display_connection));
}

void GLContextEGLWayland::UpdateDimensions(int window_width, int window_height)
{
wl_egl_window_resize(reinterpret_cast<wl_egl_window*>(m_native_window), window_width,
window_height, 0, 0);
m_backbuffer_width = window_width;
m_backbuffer_height = window_height;
}

EGLNativeWindowType GLContextEGLWayland::GetEGLNativeWindow(EGLConfig config)
{
wl_egl_window* window =
wl_egl_window_create(static_cast<wl_surface*>(m_wsi.render_surface),
m_wsi.render_surface_width, m_wsi.render_surface_height);
if (!window)
return {};

return reinterpret_cast<EGLNativeWindowType>(window);
}
19 changes: 19 additions & 0 deletions Source/Core/Common/GL/GLInterface/EGLWayland.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#pragma once

#include "Common/GL/GLInterface/EGL.h"

class GLContextEGLWayland : public GLContextEGL
{
public:
~GLContextEGLWayland();

void UpdateDimensions(int window_width, int window_height) override;

protected:
EGLDisplay OpenEGLDisplay() override;
EGLNativeWindowType GetEGLNativeWindow(EGLConfig config) override;
};
2 changes: 1 addition & 1 deletion Source/Core/Common/GL/GLInterface/EGLX11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ GLContextEGLX11::~GLContextEGLX11()
m_render_window.reset();
}

void GLContextEGLX11::Update()
void GLContextEGLX11::UpdateDimensions(int window_width, int window_height)
{
m_render_window->UpdateDimensions();
m_backbuffer_width = m_render_window->GetWidth();
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Common/GL/GLInterface/EGLX11.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class GLContextEGLX11 final : public GLContextEGL
public:
~GLContextEGLX11() override;

void Update() override;
void UpdateDimensions(int window_width, int window_height) override;

protected:
EGLDisplay OpenEGLDisplay() override;
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Common/GL/GLInterface/GLX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ bool GLContextGLX::ClearCurrent()
return glXMakeCurrent(m_display, None, nullptr);
}

void GLContextGLX::Update()
void GLContextGLX::UpdateDimensions(int window_width, int window_height)
{
m_render_window->UpdateDimensions();
m_backbuffer_width = m_render_window->GetWidth();
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Common/GL/GLInterface/GLX.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class GLContextGLX final : public GLContext
bool MakeCurrent() override;
bool ClearCurrent() override;

void Update() override;
void UpdateDimensions(int window_width, int window_height) override;

void SwapInterval(int Interval) override;
void Swap() override;
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Common/GL/GLInterface/WGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ bool GLContextWGL::ClearCurrent()
}

// Update window width, size and etc. Called from Render.cpp
void GLContextWGL::Update()
void GLContextWGL::UpdateDimensions(int window_width, int window_height)
{
RECT rcWindow;
GetClientRect(m_window_handle, &rcWindow);
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Common/GL/GLInterface/WGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class GLContextWGL final : public GLContext
bool MakeCurrent() override;
bool ClearCurrent() override;

void Update() override;
void UpdateDimensions(int window_width, int window_height) override;

void Swap() override;
void SwapInterval(int interval) override;
Expand Down
Loading