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

Add Wayland support #86180

Merged
merged 1 commit into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/linux_builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ jobs:
sudo add-apt-repository "deb https://ppa.launchpadcontent.net/kisak/turtle/ubuntu focal main"
sudo apt-get install -qq mesa-vulkan-drivers

# TODO: Figure out somehow how to embed this one.
- name: wayland-scanner dependency
run: |
sudo apt-get install libwayland-bin

- name: Free disk space on runner
run: |
echo "Disk usage before:" && df -h
Expand Down
20 changes: 20 additions & 0 deletions COPYRIGHT.txt
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,26 @@ Comment: Vulkan Memory Allocator
Copyright: 2017-2021, Advanced Micro Devices, Inc.
License: Expat

Files: ./thirdparty/wayland/
Comment: Wayland core protocol
Copyright: 2008-2012, Kristian Høgsberg
2010-2012, Intel Corporation
2011, Benjamin Franzke
2012, Collabora, Ltd.
License: Expat

Files: ./thirdparty/wayland-protocols/
Comment: Wayland protocols that add functionality not available in the core protocol
Copyright: 2008-2013, Kristian Høgsberg
2010-2013, Intel Corporation
2013, Rafael Antognolli
2013, Jasper St. Pierre
2014, Jonas Ådahl
2014, Jason Ekstrand
2014-2015, Collabora, Ltd.
2015, Red Hat Inc.
License: Expat

Files: ./thirdparty/wslay/
Comment: Wslay
Copyright: 2011, 2012, 2015, Tatsuhiro Tsujikawa
Expand Down
88 changes: 47 additions & 41 deletions doc/classes/DisplayServer.xml

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions doc/classes/EditorSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,9 @@
<member name="run/output/font_size" type="int" setter="" getter="">
The size of the font in the [b]Output[/b] panel at the bottom of the editor. This setting does not impact the font size of the script editor (see [member interface/editor/code_font_size]).
</member>
<member name="run/platforms/linuxbsd/prefer_wayland" type="bool" setter="" getter="">
If [code]true[/code], on Linux/BSD, the editor will check for Wayland first instead of X11 (if available).
</member>
<member name="run/window_placement/android_window" type="int" setter="" getter="">
The Android window to display the project on when starting the project from the editor.
[b]Note:[/b] Only available in the Android editor.
Expand Down
18 changes: 18 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,24 @@
<member name="debug/shapes/paths/geometry_width" type="float" setter="" getter="" default="2.0">
Line width of the curve path geometry, visible when "Visible Paths" is enabled in the Debug menu.
</member>
<member name="display/display_server/driver" type="String" setter="" getter="">
Sets the driver to be used by the display server. This property can not be edited directly, instead, set the driver using the platform-specific overrides.
</member>
<member name="display/display_server/driver.android" type="String" setter="" getter="">
Android override for [member display/display_server/driver].
</member>
<member name="display/display_server/driver.ios" type="String" setter="" getter="">
iOS override for [member display/display_server/driver].
</member>
<member name="display/display_server/driver.linuxbsd" type="String" setter="" getter="">
LinuxBSD override for [member display/display_server/driver].
</member>
<member name="display/display_server/driver.macos" type="String" setter="" getter="">
MacOS override for [member display/display_server/driver].
</member>
<member name="display/display_server/driver.windows" type="String" setter="" getter="">
Windows override for [member display/display_server/driver].
</member>
<member name="display/mouse_cursor/custom_image" type="String" setter="" getter="" default="&quot;&quot;">
Custom image for the mouse cursor (limited to 256×256).
</member>
Expand Down
7 changes: 5 additions & 2 deletions drivers/vulkan/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ if env["platform"] == "android":
env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_ANDROID_KHR"])
elif env["platform"] == "ios":
env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_IOS_MVK"])
elif env["platform"] == "linuxbsd" and env["x11"]:
env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_XLIB_KHR"])
elif env["platform"] == "linuxbsd":
if env["x11"]:
env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_XLIB_KHR"])
if env["wayland"]:
env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_WAYLAND_KHR"])
elif env["platform"] == "macos":
env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_MACOS_MVK"])
elif env["platform"] == "windows":
Expand Down
10 changes: 10 additions & 0 deletions editor/editor_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,10 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("run/output/always_open_output_on_play", true);
_initial_set("run/output/always_close_output_on_stop", false);

// Platform
_initial_set("run/platforms/linuxbsd/prefer_wayland", false);
set_restart_if_changed("run/platforms/linuxbsd/prefer_wayland", true);

/* Network */

// Debug
Expand Down Expand Up @@ -1419,6 +1423,12 @@ String EditorSettings::get_editor_layouts_config() const {
}

float EditorSettings::get_auto_display_scale() const {
#ifdef LINUXBSD_ENABLED
if (DisplayServer::get_singleton()->get_name() == "Wayland") {
return DisplayServer::get_singleton()->screen_get_max_scale();
}
#endif

#if defined(MACOS_ENABLED) || defined(ANDROID_ENABLED)
return DisplayServer::get_singleton()->screen_get_max_scale();
#else
Expand Down
96 changes: 67 additions & 29 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,12 @@ static bool _start_success = false;

// Drivers

String display_driver = "";
String tablet_driver = "";
String text_driver = "";
String rendering_driver = "";
String rendering_method = "";
static int text_driver_idx = -1;
static int display_driver_idx = -1;
static int audio_driver_idx = -1;

// Engine config/tools
Expand Down Expand Up @@ -824,7 +824,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
I = I->next();
}

String display_driver = "";
String audio_driver = "";
String project_path = ".";
bool upwards = false;
Expand Down Expand Up @@ -2122,23 +2121,13 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
// Display driver, e.g. X11, Wayland.
// Make sure that headless is the last one, which it is assumed to be by design.
DEV_ASSERT(NULL_DISPLAY_DRIVER == DisplayServer::get_create_function_name(DisplayServer::get_create_function_count() - 1));
for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
String name = DisplayServer::get_create_function_name(i);
if (display_driver == name) {
display_driver_idx = i;
break;
}
}

if (display_driver_idx < 0) {
// If the requested driver wasn't found, pick the first entry.
// If all else failed it would be the headless server.
display_driver_idx = 0;
}

// Store this in a globally accessible place, so we can retrieve the rendering drivers
// list from the display driver for the editor UI.
OS::get_singleton()->set_display_driver_id(display_driver_idx);
GLOBAL_DEF_RST_NOVAL("display/display_server/driver", "default");
GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.windows", PROPERTY_HINT_ENUM_SUGGESTION, "default,windows,headless"), "default");
GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.linuxbsd", PROPERTY_HINT_ENUM_SUGGESTION, "default,x11,wayland,headless"), "default");
GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.android", PROPERTY_HINT_ENUM_SUGGESTION, "default,android,headless"), "default");
GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.ios", PROPERTY_HINT_ENUM_SUGGESTION, "default,iOS,headless"), "default");
GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.macos", PROPERTY_HINT_ENUM_SUGGESTION, "default,macos,headless"), "default");

GLOBAL_DEF_RST_NOVAL("audio/driver/driver", AudioDriverManager::get_driver(0)->get_name());
if (audio_driver.is_empty()) { // Specified in project.godot.
Expand Down Expand Up @@ -2382,7 +2371,26 @@ Error Main::setup2() {
rp_new.ext_func = _parse_resource_dummy;
rp_new.sub_func = _parse_resource_dummy;

while (true) {
bool screen_found = false;
String screen_property;

bool prefer_wayland_found = false;

if (editor) {
screen_property = "interface/editor/editor_screen";
} else if (project_manager) {
screen_property = "interface/editor/project_manager_screen";
} else {
// Skip.
screen_found = true;
}

if (!display_driver.is_empty()) {
// Skip.
prefer_wayland_found = true;
}

while (!screen_found || !prefer_wayland_found) {
YuriSizov marked this conversation as resolved.
Show resolved Hide resolved
assign = Variant();
next_tag.fields.clear();
next_tag.name = String();
Expand All @@ -2391,17 +2399,21 @@ Error Main::setup2() {
if (err == ERR_FILE_EOF) {
break;
}

if (err == OK && !assign.is_empty()) {
if (project_manager) {
if (assign == "interface/editor/project_manager_screen") {
init_screen = value;
break;
}
} else if (editor) {
if (assign == "interface/editor/editor_screen") {
init_screen = value;
break;
if (!screen_found && assign == screen_property) {
init_screen = value;
screen_found = true;
}

if (!prefer_wayland_found && assign == "run/platforms/linuxbsd/prefer_wayland") {
if (value) {
display_driver = "wayland";
} else {
display_driver = "default";
}

prefer_wayland_found = true;
}
}
}
Expand Down Expand Up @@ -2459,7 +2471,33 @@ Error Main::setup2() {
{
OS::get_singleton()->benchmark_begin_measure("Servers", "Display");

String display_driver = DisplayServer::get_create_function_name(display_driver_idx);
if (display_driver.is_empty()) {
display_driver = GLOBAL_GET("display/display_server/driver");
}

Riteo marked this conversation as resolved.
Show resolved Hide resolved
int display_driver_idx = -1;

if (display_driver.is_empty() || display_driver == "default") {
display_driver_idx = 0;
} else {
for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
String name = DisplayServer::get_create_function_name(i);
if (display_driver == name) {
display_driver_idx = i;
break;
}
}

if (display_driver_idx < 0) {
// If the requested driver wasn't found, pick the first entry.
// If all else failed it would be the headless server.
display_driver_idx = 0;
}
}

// Store this in a globally accessible place, so we can retrieve the rendering drivers
// list from the display driver for the editor UI.
OS::get_singleton()->set_display_driver_id(display_driver_idx);

Vector2i *window_position = nullptr;
Vector2i position = init_custom_pos;
Expand Down
3 changes: 3 additions & 0 deletions modules/openxr/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ elif env["platform"] == "linuxbsd":
if env["x11"]:
env_openxr.AppendUnique(CPPDEFINES=["XR_USE_PLATFORM_XLIB"])

if env["wayland"]:
env_openxr.AppendUnique(CPPDEFINES=["XR_USE_PLATFORM_WAYLAND"])

# FIXME: Review what needs to be set for Android and macOS.
env_openxr.AppendUnique(CPPDEFINES=["HAVE_SECURE_GETENV"])
elif env["platform"] == "windows":
Expand Down
12 changes: 8 additions & 4 deletions modules/openxr/extensions/platform/openxr_opengl_extension.cpp
Riteo marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,9 @@ bool OpenXROpenGLExtension::check_graphics_api_support(XrVersion p_desired_versi

#ifdef WIN32
XrGraphicsBindingOpenGLWin32KHR OpenXROpenGLExtension::graphics_binding_gl;
#elif ANDROID_ENABLED
#elif defined(ANDROID_ENABLED)
XrGraphicsBindingOpenGLESAndroidKHR OpenXROpenGLExtension::graphics_binding_gl;
#else
#elif defined(X11_ENABLED)
XrGraphicsBindingOpenGLXlibKHR OpenXROpenGLExtension::graphics_binding_gl;
#endif

Expand All @@ -147,20 +147,24 @@ void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_nex

DisplayServer *display_server = DisplayServer::get_singleton();

#ifdef WAYLAND_ENABLED
ERR_FAIL_COND_V_MSG(display_server->get_name() == "Wayland", p_next_pointer, "OpenXR is not yet supported on OpenGL Wayland.");
#endif

#ifdef WIN32
graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR,
graphics_binding_gl.next = p_next_pointer;

graphics_binding_gl.hDC = (HDC)display_server->window_get_native_handle(DisplayServer::WINDOW_VIEW);
graphics_binding_gl.hGLRC = (HGLRC)display_server->window_get_native_handle(DisplayServer::OPENGL_CONTEXT);
#elif ANDROID_ENABLED
#elif defined(ANDROID_ENABLED)
graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR;
graphics_binding_gl.next = p_next_pointer;

graphics_binding_gl.display = (void *)display_server->window_get_native_handle(DisplayServer::DISPLAY_HANDLE);
graphics_binding_gl.config = (EGLConfig)0; // https://github.com/KhronosGroup/OpenXR-SDK-Source/blob/master/src/tests/hello_xr/graphicsplugin_opengles.cpp#L122
graphics_binding_gl.context = (void *)display_server->window_get_native_handle(DisplayServer::OPENGL_CONTEXT);
#else
#elif defined(X11_ENABLED)
graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR;
graphics_binding_gl.next = p_next_pointer;

Expand Down
3 changes: 3 additions & 0 deletions platform/linuxbsd/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ if env["use_sowrap"]:
if env["x11"]:
common_linuxbsd += SConscript("x11/SCsub")

if env["wayland"]:
common_linuxbsd += SConscript("wayland/SCsub")

if env["speechd"]:
common_linuxbsd.append("tts_linux.cpp")
if env["use_sowrap"]:
Expand Down
44 changes: 41 additions & 3 deletions platform/linuxbsd/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ def get_opts():
BoolVariable("fontconfig", "Use fontconfig for system fonts support", True),
BoolVariable("udev", "Use udev for gamepad connection callbacks", True),
BoolVariable("x11", "Enable X11 display", True),
BoolVariable("wayland", "Enable Wayland display", True),
Riteo marked this conversation as resolved.
Show resolved Hide resolved
BoolVariable("libdecor", "Enable libdecor support", True),
BoolVariable("touch", "Enable touch events", True),
BoolVariable("execinfo", "Use libexecinfo on systems where glibc is not available", False),
]
Expand Down Expand Up @@ -204,6 +206,11 @@ def configure(env: "Environment"):
if env["use_sowrap"]:
env.Append(CPPDEFINES=["SOWRAP_ENABLED"])

if env["wayland"]:
if os.system("wayland-scanner -v") != 0:
print("wayland-scanner not found. Aborting.")
sys.exit(255)

if env["touch"]:
env.Append(CPPDEFINES=["TOUCH_ENABLED"])

Expand Down Expand Up @@ -364,9 +371,13 @@ def configure(env: "Environment"):
env.ParseConfig("pkg-config xkbcommon --cflags --libs")
env.Append(CPPDEFINES=["XKB_ENABLED"])
else:
print(
"Warning: libxkbcommon development libraries not found. Disabling dead key composition and key label support."
)
if env["wayland"]:
print("Error: libxkbcommon development libraries required by Wayland not found. Aborting.")
Riteo marked this conversation as resolved.
Show resolved Hide resolved
sys.exit(255)
else:
print(
"Warning: libxkbcommon development libraries not found. Disabling dead key composition and key label support."
)
else:
env.Append(CPPDEFINES=["XKB_ENABLED"])

Expand Down Expand Up @@ -433,6 +444,33 @@ def configure(env: "Environment"):
env.ParseConfig("pkg-config xi --cflags --libs")
env.Append(CPPDEFINES=["X11_ENABLED"])

if env["wayland"]:
if not env["use_sowrap"]:
if os.system("pkg-config --exists libdecor-0"):
print("Warning: libdecor development libraries not found. Disabling client-side decorations.")
env["libdecor"] = False
else:
env.ParseConfig("pkg-config libdecor-0 --cflags --libs")
if os.system("pkg-config --exists wayland-client"):
print("Error: Wayland client library not found. Aborting.")
sys.exit(255)
env.ParseConfig("pkg-config wayland-client --cflags --libs")
if os.system("pkg-config --exists wayland-cursor"):
print("Error: Wayland cursor library not found. Aborting.")
sys.exit(255)
env.ParseConfig("pkg-config wayland-cursor --cflags --libs")
if os.system("pkg-config --exists wayland-egl"):
print("Error: Wayland EGL library not found. Aborting.")
sys.exit(255)
env.ParseConfig("pkg-config wayland-egl --cflags --libs")

if env["libdecor"]:
env.Append(CPPDEFINES=["LIBDECOR_ENABLED"])

env.Prepend(CPPPATH=["#platform/linuxbsd", "#thirdparty/linuxbsd_headers/wayland/"])
env.Append(CPPDEFINES=["WAYLAND_ENABLED"])
env.Append(LIBS=["rt"]) # Needed by glibc, used by _allocate_shm_file

if env["vulkan"]:
env.Append(CPPDEFINES=["VULKAN_ENABLED", "RD_ENABLED"])
if not env["use_volk"]:
Expand Down
2 changes: 1 addition & 1 deletion platform/linuxbsd/export/export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void register_linuxbsd_exporter_types() {
void register_linuxbsd_exporter() {
Ref<EditorExportPlatformLinuxBSD> platform;
platform.instantiate();
platform->set_name("Linux/X11");
platform->set_name("Linux");
platform->set_os_name("Linux");
platform->set_chmod_flags(0755);

Expand Down