diff options
Diffstat (limited to 'platform/linuxbsd')
-rw-r--r-- | platform/linuxbsd/SCsub | 1 | ||||
-rw-r--r-- | platform/linuxbsd/detect.py | 4 | ||||
-rw-r--r-- | platform/linuxbsd/export/export_plugin.cpp | 109 | ||||
-rw-r--r-- | platform/linuxbsd/export/export_plugin.h | 8 | ||||
-rw-r--r-- | platform/linuxbsd/freedesktop_portal_desktop.cpp | 27 | ||||
-rw-r--r-- | platform/linuxbsd/joypad_linux.cpp | 2 | ||||
-rw-r--r-- | platform/linuxbsd/wayland/SCsub | 1 | ||||
-rw-r--r-- | platform/linuxbsd/wayland/display_server_wayland.cpp | 105 | ||||
-rw-r--r-- | platform/linuxbsd/wayland/key_mapping_xkb.h | 2 | ||||
-rw-r--r-- | platform/linuxbsd/wayland/rendering_context_driver_vulkan_wayland.cpp | 8 | ||||
-rw-r--r-- | platform/linuxbsd/wayland/wayland_thread.cpp | 177 | ||||
-rw-r--r-- | platform/linuxbsd/wayland/wayland_thread.h | 23 | ||||
-rw-r--r-- | platform/linuxbsd/x11/SCsub | 1 | ||||
-rw-r--r-- | platform/linuxbsd/x11/display_server_x11.cpp | 104 | ||||
-rw-r--r-- | platform/linuxbsd/x11/gl_manager_x11_egl.h | 4 | ||||
-rw-r--r-- | platform/linuxbsd/x11/rendering_context_driver_vulkan_x11.cpp | 8 |
16 files changed, 362 insertions, 222 deletions
diff --git a/platform/linuxbsd/SCsub b/platform/linuxbsd/SCsub index 0802b528f4..4def765e9c 100644 --- a/platform/linuxbsd/SCsub +++ b/platform/linuxbsd/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index d1de760f34..a67434527c 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -256,10 +256,6 @@ def configure(env: "SConsEnvironment"): if not env["builtin_enet"]: env.ParseConfig("pkg-config libenet --cflags --libs") - if not env["builtin_squish"]: - # libsquish doesn't reliably install its .pc file, so some distros lack it. - env.Append(LIBS=["libsquish"]) - if not env["builtin_zstd"]: env.ParseConfig("pkg-config libzstd --cflags --libs") diff --git a/platform/linuxbsd/export/export_plugin.cpp b/platform/linuxbsd/export/export_plugin.cpp index 936adddda3..69ba742f72 100644 --- a/platform/linuxbsd/export/export_plugin.cpp +++ b/platform/linuxbsd/export/export_plugin.cpp @@ -60,7 +60,21 @@ Error EditorExportPlatformLinuxBSD::_export_debug_script(const Ref<EditorExportP return OK; } -Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { +Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) { + String custom_debug = p_preset->get("custom_template/debug"); + String custom_release = p_preset->get("custom_template/release"); + String arch = p_preset->get("binary_format/architecture"); + + String template_path = p_debug ? custom_debug : custom_release; + template_path = template_path.strip_edges(); + if (!template_path.is_empty()) { + String exe_arch = _get_exe_arch(template_path); + if (arch != exe_arch) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), vformat(TTR("Mismatching custom export template executable architecture, found \"%s\", expected \"%s\"."), exe_arch, arch)); + return ERR_CANT_CREATE; + } + } + bool export_as_zip = p_path.ends_with("zip"); String pkg_name; @@ -205,8 +219,76 @@ bool EditorExportPlatformLinuxBSD::is_executable(const String &p_path) const { return is_elf(p_path) || is_shebang(p_path); } +bool EditorExportPlatformLinuxBSD::has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug) const { + String err; + bool valid = EditorExportPlatformPC::has_valid_export_configuration(p_preset, err, r_missing_templates, p_debug); + + String custom_debug = p_preset->get("custom_template/debug").operator String().strip_edges(); + String custom_release = p_preset->get("custom_template/release").operator String().strip_edges(); + String arch = p_preset->get("binary_format/architecture"); + + if (!custom_debug.is_empty() && FileAccess::exists(custom_debug)) { + String exe_arch = _get_exe_arch(custom_debug); + if (arch != exe_arch) { + err += vformat(TTR("Mismatching custom debug export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch) + "\n"; + } + } + if (!custom_release.is_empty() && FileAccess::exists(custom_release)) { + String exe_arch = _get_exe_arch(custom_release); + if (arch != exe_arch) { + err += vformat(TTR("Mismatching custom release export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch) + "\n"; + } + } + + if (!err.is_empty()) { + r_error = err; + } + + return valid; +} + +String EditorExportPlatformLinuxBSD::_get_exe_arch(const String &p_path) const { + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); + if (f.is_null()) { + return "invalid"; + } + + // Read and check ELF magic number. + { + uint32_t magic = f->get_32(); + if (magic != 0x464c457f) { // 0x7F + "ELF" + return "invalid"; + } + } + + // Process header. + int64_t header_pos = f->get_position(); + f->seek(header_pos + 14); + uint16_t machine = f->get_16(); + f->close(); + + switch (machine) { + case 0x0003: + return "x86_32"; + case 0x003e: + return "x86_64"; + case 0x0014: + return "ppc32"; + case 0x0015: + return "ppc64"; + case 0x0028: + return "arm32"; + case 0x00b7: + return "arm64"; + case 0x00f3: + return "rv64"; + default: + return "unknown"; + } +} + Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) { - // Patch the header of the "pck" section in the ELF file so that it corresponds to the embedded data + // Patch the header of the "pck" section in the ELF file so that it corresponds to the embedded data. Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ_WRITE); if (f.is_null()) { @@ -214,7 +296,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int return ERR_CANT_OPEN; } - // Read and check ELF magic number + // Read and check ELF magic number. { uint32_t magic = f->get_32(); if (magic != 0x464c457f) { // 0x7F + "ELF" @@ -223,7 +305,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int } } - // Read program architecture bits from class field + // Read program architecture bits from class field. int bits = f->get_8() * 32; @@ -231,7 +313,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("32-bit executables cannot have embedded data >= 4 GiB.")); } - // Get info about the section header table + // Get info about the section header table. int64_t section_table_pos; int64_t section_header_size; @@ -249,13 +331,13 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int int num_sections = f->get_16(); int string_section_idx = f->get_16(); - // Load the strings table + // Load the strings table. uint8_t *strings; { - // Jump to the strings section header + // Jump to the strings section header. f->seek(section_table_pos + string_section_idx * section_header_size); - // Read strings data size and offset + // Read strings data size and offset. int64_t string_data_pos; int64_t string_data_size; if (bits == 32) { @@ -268,7 +350,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int string_data_size = f->get_64(); } - // Read strings data + // Read strings data. f->seek(string_data_pos); strings = (uint8_t *)memalloc(string_data_size); if (!strings) { @@ -277,7 +359,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int f->get_buffer(strings, string_data_size); } - // Search for the "pck" section + // Search for the "pck" section. bool found = false; for (int i = 0; i < num_sections; ++i) { @@ -376,7 +458,7 @@ void EditorExportPlatformLinuxBSD::cleanup() { cleanup_commands.clear(); } -Error EditorExportPlatformLinuxBSD::run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) { +Error EditorExportPlatformLinuxBSD::run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) { cleanup(); if (p_device) { // Stop command, cleanup only. return OK; @@ -430,8 +512,7 @@ Error EditorExportPlatformLinuxBSD::run(const Ref<EditorExportPreset> &p_preset, String cmd_args; { - Vector<String> cmd_args_list; - gen_debug_flags(cmd_args_list, p_debug_flags); + Vector<String> cmd_args_list = gen_export_flags(p_debug_flags); for (int i = 0; i < cmd_args_list.size(); i++) { if (i != 0) { cmd_args += " "; @@ -440,7 +521,7 @@ Error EditorExportPlatformLinuxBSD::run(const Ref<EditorExportPreset> &p_preset, } } - const bool use_remote = (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) || (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT); + const bool use_remote = p_debug_flags.has_flag(DEBUG_FLAG_REMOTE_DEBUG) || p_debug_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT); int dbg_port = EditorSettings::get_singleton()->get("network/debug/remote_port"); print_line("Creating temporary directory..."); diff --git a/platform/linuxbsd/export/export_plugin.h b/platform/linuxbsd/export/export_plugin.h index 21bd81ed2f..9e016bd4c3 100644 --- a/platform/linuxbsd/export/export_plugin.h +++ b/platform/linuxbsd/export/export_plugin.h @@ -48,7 +48,7 @@ class EditorExportPlatformLinuxBSD : public EditorExportPlatformPC { String cmd_args; bool wait = false; - SSHCleanupCommand(){}; + SSHCleanupCommand() {} SSHCleanupCommand(const String &p_host, const String &p_port, const Vector<String> &p_ssh_arg, const String &p_cmd_args, bool p_wait = false) { host = p_host; port = p_port; @@ -69,12 +69,14 @@ class EditorExportPlatformLinuxBSD : public EditorExportPlatformPC { bool is_shebang(const String &p_path) const; Error _export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path); + String _get_exe_arch(const String &p_path) const; public: virtual void get_export_options(List<ExportOption> *r_options) const override; virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override; virtual bool get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option) const override; - virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override; + virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override; + virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override; virtual String get_template_file_name(const String &p_target, const String &p_arch) const override; virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) override; virtual bool is_executable(const String &p_path) const override; @@ -85,7 +87,7 @@ public: virtual int get_options_count() const override; virtual String get_option_label(int p_index) const override; virtual String get_option_tooltip(int p_index) const override; - virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) override; + virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) override; virtual void cleanup() override; EditorExportPlatformLinuxBSD(); diff --git a/platform/linuxbsd/freedesktop_portal_desktop.cpp b/platform/linuxbsd/freedesktop_portal_desktop.cpp index 671da7fc2a..94a748e414 100644 --- a/platform/linuxbsd/freedesktop_portal_desktop.cpp +++ b/platform/linuxbsd/freedesktop_portal_desktop.cpp @@ -210,7 +210,15 @@ void FreeDesktopPortalDesktop::append_dbus_dict_filters(DBusMessageIter *p_iter, append_dbus_string(&struct_iter, p_filter_names[i]); dbus_message_iter_open_container(&struct_iter, DBUS_TYPE_ARRAY, "(us)", &array_iter); - const String &flt = p_filter_exts[i]; + const String &flt_orig = p_filter_exts[i]; + String flt; + for (int j = 0; j < flt_orig.length(); j++) { + if (is_unicode_letter(flt_orig[j])) { + flt += vformat("[%c%c]", String::char_lowercase(flt_orig[j]), String::char_uppercase(flt_orig[j])); + } else { + flt += flt_orig[j]; + } + } int filter_slice_count = flt.get_slice_count(","); for (int j = 0; j < filter_slice_count; j++) { dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, nullptr, &array_struct_iter); @@ -377,17 +385,26 @@ Error FreeDesktopPortalDesktop::file_dialog_show(DisplayServer::WindowID p_windo String flt = tokens[0].strip_edges(); if (!flt.is_empty()) { if (tokens.size() == 2) { - filter_exts.push_back(flt); + if (flt == "*.*") { + filter_exts.push_back("*"); + } else { + filter_exts.push_back(flt); + } filter_names.push_back(tokens[1]); } else { - filter_exts.push_back(flt); - filter_names.push_back(flt); + if (flt == "*.*") { + filter_exts.push_back("*"); + filter_names.push_back(RTR("All Files")); + } else { + filter_exts.push_back(flt); + filter_names.push_back(flt); + } } } } } if (filter_names.is_empty()) { - filter_exts.push_back("*.*"); + filter_exts.push_back("*"); filter_names.push_back(RTR("All Files")); } diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp index a67428b9a4..49f2690e61 100644 --- a/platform/linuxbsd/joypad_linux.cpp +++ b/platform/linuxbsd/joypad_linux.cpp @@ -50,7 +50,7 @@ #define LONG_BITS (sizeof(long) * 8) #define test_bit(nr, addr) (((1UL << ((nr) % LONG_BITS)) & ((addr)[(nr) / LONG_BITS])) != 0) -#define NBITS(x) ((((x)-1) / LONG_BITS) + 1) +#define NBITS(x) ((((x) - 1) / LONG_BITS) + 1) #ifdef UDEV_ENABLED static const char *ignore_str = "/dev/input/js"; diff --git a/platform/linuxbsd/wayland/SCsub b/platform/linuxbsd/wayland/SCsub index 89b586845c..1a8e243728 100644 --- a/platform/linuxbsd/wayland/SCsub +++ b/platform/linuxbsd/wayland/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp index 93096fcdcc..71c721ca1d 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.cpp +++ b/platform/linuxbsd/wayland/display_server_wayland.cpp @@ -327,15 +327,7 @@ void DisplayServerWayland::mouse_set_mode(MouseMode p_mode) { bool show_cursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED); - if (show_cursor) { - if (custom_cursors.has(cursor_shape)) { - wayland_thread.cursor_set_custom_shape(cursor_shape); - } else { - wayland_thread.cursor_set_shape(cursor_shape); - } - } else { - wayland_thread.cursor_hide(); - } + wayland_thread.cursor_set_visible(show_cursor); WaylandThread::PointerConstraint constraint = WaylandThread::PointerConstraint::NONE; @@ -480,7 +472,7 @@ String DisplayServerWayland::clipboard_get_primary() const { for (String mime : text_mimes) { if (wayland_thread.primary_has_mime(mime)) { print_verbose(vformat("Selecting media type \"%s\" from offered types.", mime)); - wayland_thread.primary_get_mime(mime); + data = wayland_thread.primary_get_mime(mime); break; } } @@ -993,11 +985,7 @@ void DisplayServerWayland::cursor_set_shape(CursorShape p_shape) { return; } - if (custom_cursors.has(p_shape)) { - wayland_thread.cursor_set_custom_shape(p_shape); - } else { - wayland_thread.cursor_set_shape(p_shape); - } + wayland_thread.cursor_set_shape(p_shape); } DisplayServerWayland::CursorShape DisplayServerWayland::cursor_get_shape() const { @@ -1009,18 +997,13 @@ DisplayServerWayland::CursorShape DisplayServerWayland::cursor_get_shape() const void DisplayServerWayland::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { MutexLock mutex_lock(wayland_thread.mutex); - bool visible = (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED); - if (p_cursor.is_valid()) { HashMap<CursorShape, CustomCursor>::Iterator cursor_c = custom_cursors.find(p_shape); if (cursor_c) { if (cursor_c->value.rid == p_cursor->get_rid() && cursor_c->value.hotspot == p_hotspot) { // We have a cached cursor. Nice. - if (visible) { - wayland_thread.cursor_set_custom_shape(p_shape); - } - + wayland_thread.cursor_set_shape(p_shape); return; } @@ -1039,20 +1022,18 @@ void DisplayServerWayland::cursor_set_custom_image(const Ref<Resource> &p_cursor wayland_thread.cursor_shape_set_custom_image(p_shape, image, p_hotspot); - if (visible) { - wayland_thread.cursor_set_custom_shape(p_shape); - } + wayland_thread.cursor_set_shape(p_shape); } else { // Clear cache and reset to default system cursor. - if (cursor_shape == p_shape && visible) { + wayland_thread.cursor_shape_clear_custom_image(p_shape); + + if (cursor_shape == p_shape) { wayland_thread.cursor_set_shape(p_shape); } if (custom_cursors.has(p_shape)) { custom_cursors.erase(p_shape); } - - wayland_thread.cursor_shape_clear_custom_image(p_shape); } } @@ -1349,23 +1330,47 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win rendering_driver = p_rendering_driver; + bool driver_found = false; + String executable_name = OS::get_singleton()->get_executable_path().get_file(); + #ifdef RD_ENABLED #ifdef VULKAN_ENABLED if (rendering_driver == "vulkan") { rendering_context = memnew(RenderingContextDriverVulkanWayland); } -#endif +#endif // VULKAN_ENABLED if (rendering_context) { if (rendering_context->initialize() != OK) { - ERR_PRINT(vformat("Could not initialize %s", rendering_driver)); memdelete(rendering_context); rendering_context = nullptr; - r_error = ERR_CANT_CREATE; - return; + bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3"); + if (fallback_to_opengl3 && rendering_driver != "opengl3") { + WARN_PRINT("Your video card drivers seem not to support the required Vulkan version, switching to OpenGL 3."); + rendering_driver = "opengl3"; + OS::get_singleton()->set_current_rendering_method("gl_compatibility"); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); + } else { + r_error = ERR_CANT_CREATE; + + if (p_rendering_driver == "vulkan") { + OS::get_singleton()->alert( + vformat("Your video card drivers seem not to support the required Vulkan version.\n\n" + "If possible, consider updating your video card drivers or using the OpenGL 3 driver.\n\n" + "You can enable the OpenGL 3 driver by starting the engine from the\n" + "command line with the command:\n\n \"%s\" --rendering-driver opengl3\n\n" + "If you recently updated your video card drivers, try rebooting.", + executable_name), + "Unable to initialize Vulkan video driver"); + } + + ERR_FAIL_MSG(vformat("Could not initialize %s", rendering_driver)); + } } + + driver_found = true; } -#endif +#endif // RD_ENABLED #ifdef GLES3_ENABLED if (rendering_driver == "opengl3" || rendering_driver == "opengl3_es") { @@ -1429,30 +1434,58 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win if (fallback) { WARN_PRINT("Your video card drivers seem not to support the required OpenGL version, switching to OpenGLES."); rendering_driver = "opengl3_es"; + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); } else { r_error = ERR_UNAVAILABLE; + + OS::get_singleton()->alert( + vformat("Your video card drivers seem not to support the required OpenGL 3.3 version.\n\n" + "If possible, consider updating your video card drivers or using the Vulkan driver.\n\n" + "You can enable the Vulkan driver by starting the engine from the\n" + "command line with the command:\n\n \"%s\" --rendering-driver vulkan\n\n" + "If you recently updated your video card drivers, try rebooting.", + executable_name), + "Unable to initialize OpenGL video driver"); + ERR_FAIL_MSG("Could not initialize OpenGL."); } } else { RasterizerGLES3::make_current(true); + driver_found = true; } } if (rendering_driver == "opengl3_es") { egl_manager = memnew(EGLManagerWaylandGLES); - if (egl_manager->initialize(wayland_thread.get_wl_display()) != OK) { + if (egl_manager->initialize(wayland_thread.get_wl_display()) != OK || egl_manager->open_display(wayland_thread.get_wl_display()) != OK) { memdelete(egl_manager); egl_manager = nullptr; r_error = ERR_CANT_CREATE; - ERR_FAIL_MSG("Could not initialize GLES3."); + + OS::get_singleton()->alert( + vformat("Your video card drivers seem not to support the required OpenGL ES 3.0 version.\n\n" + "If possible, consider updating your video card drivers or using the Vulkan driver.\n\n" + "You can enable the Vulkan driver by starting the engine from the\n" + "command line with the command:\n\n \"%s\" --rendering-driver vulkan\n\n" + "If you recently updated your video card drivers, try rebooting.", + executable_name), + "Unable to initialize OpenGL ES video driver"); + + ERR_FAIL_MSG("Could not initialize OpenGL ES."); } RasterizerGLES3::make_current(false); + driver_found = true; } } #endif // GLES3_ENABLED + if (!driver_found) { + r_error = ERR_UNAVAILABLE; + ERR_FAIL_MSG("Video driver not found."); + } + cursor_set_shape(CURSOR_BUSY); WindowData &wd = main_window; @@ -1481,12 +1514,12 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win RendererCompositorRD::make_current(); } -#endif +#endif // RD_ENABLED #ifdef DBUS_ENABLED portal_desktop = memnew(FreeDesktopPortalDesktop); screensaver = memnew(FreeDesktopScreenSaver); -#endif +#endif // DBUS_ENABLED screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on")); diff --git a/platform/linuxbsd/wayland/key_mapping_xkb.h b/platform/linuxbsd/wayland/key_mapping_xkb.h index 306a8f25b5..9b8c90a445 100644 --- a/platform/linuxbsd/wayland/key_mapping_xkb.h +++ b/platform/linuxbsd/wayland/key_mapping_xkb.h @@ -51,7 +51,7 @@ class KeyMappingXKB { static inline HashMap<Key, unsigned int, HashMapHasherKeys> scancode_map_inv; static inline HashMap<unsigned int, KeyLocation, HashMapHasherKeys> location_map; - KeyMappingXKB(){}; + KeyMappingXKB() {} public: static void initialize(); diff --git a/platform/linuxbsd/wayland/rendering_context_driver_vulkan_wayland.cpp b/platform/linuxbsd/wayland/rendering_context_driver_vulkan_wayland.cpp index c874c45a8a..8abcc464ba 100644 --- a/platform/linuxbsd/wayland/rendering_context_driver_vulkan_wayland.cpp +++ b/platform/linuxbsd/wayland/rendering_context_driver_vulkan_wayland.cpp @@ -32,11 +32,7 @@ #include "rendering_context_driver_vulkan_wayland.h" -#ifdef USE_VOLK -#include <volk.h> -#else -#include <vulkan/vulkan.h> -#endif +#include "drivers/vulkan/godot_vulkan.h" const char *RenderingContextDriverVulkanWayland::_get_platform_surface_extension() const { return VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME; @@ -51,7 +47,7 @@ RenderingContextDriver::SurfaceID RenderingContextDriverVulkanWayland::surface_c create_info.surface = wpd->surface; VkSurfaceKHR vk_surface = VK_NULL_HANDLE; - VkResult err = vkCreateWaylandSurfaceKHR(instance_get(), &create_info, nullptr, &vk_surface); + VkResult err = vkCreateWaylandSurfaceKHR(instance_get(), &create_info, get_allocation_callbacks(VK_OBJECT_TYPE_SURFACE_KHR), &vk_surface); ERR_FAIL_COND_V(err != VK_SUCCESS, SurfaceID()); Surface *surface = memnew(Surface); diff --git a/platform/linuxbsd/wayland/wayland_thread.cpp b/platform/linuxbsd/wayland/wayland_thread.cpp index dea8bae438..e066e78e5b 100644 --- a/platform/linuxbsd/wayland/wayland_thread.cpp +++ b/platform/linuxbsd/wayland/wayland_thread.cpp @@ -169,12 +169,13 @@ Vector<uint8_t> WaylandThread::_wp_primary_selection_offer_read(struct wl_displa int fds[2]; if (pipe(fds) == 0) { - // This function expects to return a string, so we can only ask for a MIME of - // "text/plain" zwp_primary_selection_offer_v1_receive(p_offer, p_mime, fds[1]); - // Wait for the compositor to know about the pipe. - wl_display_roundtrip(p_display); + // NOTE: It's important to just flush and not roundtrip here as we would risk + // running some cleanup event, like for example `wl_data_device::leave`. We're + // going to wait for the message anyways as the read will probably block if + // the compositor doesn't read from the other end of the pipe. + wl_display_flush(p_display); // Close the write end of the pipe, which we don't need and would otherwise // just stall our next `read`s. @@ -264,8 +265,6 @@ bool WaylandThread::_load_cursor_theme(int p_cursor_size) { if (wl_cursor_theme) { wl_cursor_theme_destroy(wl_cursor_theme); wl_cursor_theme = nullptr; - - current_wl_cursor = nullptr; } if (cursor_theme_name.is_empty()) { @@ -356,7 +355,12 @@ void WaylandThread::_update_scale(int p_scale) { int cursor_size = unscaled_cursor_size * p_scale; if (_load_cursor_theme(cursor_size)) { - cursor_set_shape(last_cursor_shape); + for (struct wl_seat *wl_seat : registry.wl_seats) { + SeatState *ss = wl_seat_get_seat_state(wl_seat); + ERR_FAIL_NULL(ss); + + seat_state_update_cursor(ss); + } } } @@ -1263,23 +1267,25 @@ void WaylandThread::_wl_seat_on_capabilities(void *data, struct wl_seat *wl_seat // Pointer handling. if (capabilities & WL_SEAT_CAPABILITY_POINTER) { - ss->cursor_surface = wl_compositor_create_surface(ss->registry->wl_compositor); - wl_surface_commit(ss->cursor_surface); + if (!ss->wl_pointer) { + ss->cursor_surface = wl_compositor_create_surface(ss->registry->wl_compositor); + wl_surface_commit(ss->cursor_surface); - ss->wl_pointer = wl_seat_get_pointer(wl_seat); - wl_pointer_add_listener(ss->wl_pointer, &wl_pointer_listener, ss); + ss->wl_pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_add_listener(ss->wl_pointer, &wl_pointer_listener, ss); - if (ss->registry->wp_relative_pointer_manager) { - ss->wp_relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(ss->registry->wp_relative_pointer_manager, ss->wl_pointer); - zwp_relative_pointer_v1_add_listener(ss->wp_relative_pointer, &wp_relative_pointer_listener, ss); - } + if (ss->registry->wp_relative_pointer_manager) { + ss->wp_relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(ss->registry->wp_relative_pointer_manager, ss->wl_pointer); + zwp_relative_pointer_v1_add_listener(ss->wp_relative_pointer, &wp_relative_pointer_listener, ss); + } - if (ss->registry->wp_pointer_gestures) { - ss->wp_pointer_gesture_pinch = zwp_pointer_gestures_v1_get_pinch_gesture(ss->registry->wp_pointer_gestures, ss->wl_pointer); - zwp_pointer_gesture_pinch_v1_add_listener(ss->wp_pointer_gesture_pinch, &wp_pointer_gesture_pinch_listener, ss); - } + if (ss->registry->wp_pointer_gestures) { + ss->wp_pointer_gesture_pinch = zwp_pointer_gestures_v1_get_pinch_gesture(ss->registry->wp_pointer_gestures, ss->wl_pointer); + zwp_pointer_gesture_pinch_v1_add_listener(ss->wp_pointer_gesture_pinch, &wp_pointer_gesture_pinch_listener, ss); + } - // TODO: Constrain new pointers if the global mouse mode is constrained. + // TODO: Constrain new pointers if the global mouse mode is constrained. + } } else { if (ss->cursor_frame_callback) { // Just in case. I got bitten by weird race-like conditions already. @@ -1317,11 +1323,13 @@ void WaylandThread::_wl_seat_on_capabilities(void *data, struct wl_seat *wl_seat // Keyboard handling. if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { - ss->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - ERR_FAIL_NULL(ss->xkb_context); + if (!ss->wl_keyboard) { + ss->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + ERR_FAIL_NULL(ss->xkb_context); - ss->wl_keyboard = wl_seat_get_keyboard(wl_seat); - wl_keyboard_add_listener(ss->wl_keyboard, &wl_keyboard_listener, ss); + ss->wl_keyboard = wl_seat_get_keyboard(wl_seat); + wl_keyboard_add_listener(ss->wl_keyboard, &wl_keyboard_listener, ss); + } } else { if (ss->xkb_context) { xkb_context_unref(ss->xkb_context); @@ -1390,6 +1398,8 @@ void WaylandThread::_wl_pointer_on_leave(void *data, struct wl_pointer *wl_point ss->pointed_surface = nullptr; + ss->pointer_data_buffer.pressed_button_mask.clear(); + Ref<WindowEventMessage> msg; msg.instantiate(); msg->event = DisplayServer::WINDOW_EVENT_MOUSE_EXIT; @@ -1412,10 +1422,10 @@ void WaylandThread::_wl_pointer_on_motion(void *data, struct wl_pointer *wl_poin PointerData &pd = ss->pointer_data_buffer; // TODO: Scale only when sending the Wayland message. - pd.position.x = wl_fixed_to_int(surface_x); - pd.position.y = wl_fixed_to_int(surface_y); + pd.position.x = wl_fixed_to_double(surface_x); + pd.position.y = wl_fixed_to_double(surface_y); - pd.position = scale_vector2i(pd.position, window_state_get_scale_factor(ws)); + pd.position *= window_state_get_scale_factor(ws); pd.motion_time = time; } @@ -1528,7 +1538,7 @@ void WaylandThread::_wl_pointer_on_frame(void *data, struct wl_pointer *wl_point mm->set_position(pd.position); mm->set_global_position(pd.position); - Vector2i pos_delta = pd.position - old_pd.position; + Vector2 pos_delta = pd.position - old_pd.position; if (old_pd.relative_motion_time != pd.relative_motion_time) { uint32_t time_delta = pd.relative_motion_time - old_pd.relative_motion_time; @@ -1645,7 +1655,7 @@ void WaylandThread::_wl_pointer_on_frame(void *data, struct wl_pointer *wl_point // We have to set the last position pressed here as we can't take for // granted what the individual events might have seen due to them not having - // a garaunteed order. + // a guaranteed order. if (mb->is_pressed()) { pd.last_pressed_position = pd.position; } @@ -2384,9 +2394,9 @@ void WaylandThread::_wp_tablet_tool_on_motion(void *data, struct zwp_tablet_tool double scale_factor = window_state_get_scale_factor(ws); - td.position.x = wl_fixed_to_int(x); - td.position.y = wl_fixed_to_int(y); - td.position = scale_vector2i(td.position, scale_factor); + td.position.x = wl_fixed_to_double(x); + td.position.y = wl_fixed_to_double(y); + td.position *= scale_factor; td.motion_time = OS::get_singleton()->get_ticks_msec(); } @@ -2516,7 +2526,7 @@ void WaylandThread::_wp_tablet_tool_on_frame(void *data, struct zwp_tablet_tool_ mm->set_relative(td.position - old_td.position); mm->set_relative_screen_position(mm->get_relative()); - Vector2i pos_delta = td.position - old_td.position; + Vector2 pos_delta = td.position - old_td.position; uint32_t time_delta = td.motion_time - old_td.motion_time; mm->set_velocity((Vector2)pos_delta / time_delta); @@ -3067,19 +3077,25 @@ void WaylandThread::seat_state_confine_pointer(SeatState *p_ss) { void WaylandThread::seat_state_update_cursor(SeatState *p_ss) { ERR_FAIL_NULL(p_ss); + + WaylandThread *thread = p_ss->wayland_thread; ERR_FAIL_NULL(p_ss->wayland_thread); - if (p_ss->wl_pointer && p_ss->cursor_surface) { - // NOTE: Those values are valid by default and will hide the cursor when - // unchanged, which happens when both the current custom cursor and the - // current wl_cursor are `nullptr`. - struct wl_buffer *cursor_buffer = nullptr; - uint32_t hotspot_x = 0; - uint32_t hotspot_y = 0; - int scale = 1; + if (!p_ss->wl_pointer || !p_ss->cursor_surface) { + return; + } + + // NOTE: Those values are valid by default and will hide the cursor when + // unchanged. + struct wl_buffer *cursor_buffer = nullptr; + uint32_t hotspot_x = 0; + uint32_t hotspot_y = 0; + int scale = 1; + + if (thread->cursor_visible) { + DisplayServer::CursorShape shape = thread->cursor_shape; - CustomCursor *custom_cursor = p_ss->wayland_thread->current_custom_cursor; - struct wl_cursor *wl_cursor = p_ss->wayland_thread->current_wl_cursor; + struct CustomCursor *custom_cursor = thread->custom_cursors.getptr(shape); if (custom_cursor) { cursor_buffer = custom_cursor->wl_buffer; @@ -3089,7 +3105,13 @@ void WaylandThread::seat_state_update_cursor(SeatState *p_ss) { // We can't really reasonably scale custom cursors, so we'll let the // compositor do it for us (badly). scale = 1; - } else if (wl_cursor) { + } else { + struct wl_cursor *wl_cursor = thread->wl_cursors[shape]; + + if (!wl_cursor) { + return; + } + int frame_idx = 0; if (wl_cursor->image_count > 1) { @@ -3105,24 +3127,24 @@ void WaylandThread::seat_state_update_cursor(SeatState *p_ss) { struct wl_cursor_image *wl_cursor_image = wl_cursor->images[frame_idx]; - scale = p_ss->wayland_thread->cursor_scale; + scale = thread->cursor_scale; cursor_buffer = wl_cursor_image_get_buffer(wl_cursor_image); // As the surface's buffer is scaled (thus the surface is smaller) and the // hotspot must be expressed in surface-local coordinates, we need to scale - // them down accordingly. + // it down accordingly. hotspot_x = wl_cursor_image->hotspot_x / scale; hotspot_y = wl_cursor_image->hotspot_y / scale; } + } - wl_pointer_set_cursor(p_ss->wl_pointer, p_ss->pointer_enter_serial, p_ss->cursor_surface, hotspot_x, hotspot_y); - wl_surface_set_buffer_scale(p_ss->cursor_surface, scale); - wl_surface_attach(p_ss->cursor_surface, cursor_buffer, 0, 0); - wl_surface_damage_buffer(p_ss->cursor_surface, 0, 0, INT_MAX, INT_MAX); + wl_pointer_set_cursor(p_ss->wl_pointer, p_ss->pointer_enter_serial, p_ss->cursor_surface, hotspot_x, hotspot_y); + wl_surface_set_buffer_scale(p_ss->cursor_surface, scale); + wl_surface_attach(p_ss->cursor_surface, cursor_buffer, 0, 0); + wl_surface_damage_buffer(p_ss->cursor_surface, 0, 0, INT_MAX, INT_MAX); - wl_surface_commit(p_ss->cursor_surface); - } + wl_surface_commit(p_ss->cursor_surface); } void WaylandThread::seat_state_echo_keys(SeatState *p_ss) { @@ -3763,25 +3785,8 @@ Error WaylandThread::init() { return OK; } -void WaylandThread::cursor_hide() { - current_wl_cursor = nullptr; - current_custom_cursor = nullptr; - - SeatState *ss = wl_seat_get_seat_state(wl_seat_current); - ERR_FAIL_NULL(ss); - seat_state_update_cursor(ss); -} - -void WaylandThread::cursor_set_shape(DisplayServer::CursorShape p_cursor_shape) { - if (!wl_cursors[p_cursor_shape]) { - return; - } - - // The point of this method is make the current cursor a "plain" shape and, as - // the custom cursor overrides what gets set, we have to clear it too. - current_custom_cursor = nullptr; - - current_wl_cursor = wl_cursors[p_cursor_shape]; +void WaylandThread::cursor_set_visible(bool p_visible) { + cursor_visible = p_visible; for (struct wl_seat *wl_seat : registry.wl_seats) { SeatState *ss = wl_seat_get_seat_state(wl_seat); @@ -3789,14 +3794,10 @@ void WaylandThread::cursor_set_shape(DisplayServer::CursorShape p_cursor_shape) seat_state_update_cursor(ss); } - - last_cursor_shape = p_cursor_shape; } -void WaylandThread::cursor_set_custom_shape(DisplayServer::CursorShape p_cursor_shape) { - ERR_FAIL_COND(!custom_cursors.has(p_cursor_shape)); - - current_custom_cursor = &custom_cursors[p_cursor_shape]; +void WaylandThread::cursor_set_shape(DisplayServer::CursorShape p_cursor_shape) { + cursor_shape = p_cursor_shape; for (struct wl_seat *wl_seat : registry.wl_seats) { SeatState *ss = wl_seat_get_seat_state(wl_seat); @@ -3804,8 +3805,6 @@ void WaylandThread::cursor_set_custom_shape(DisplayServer::CursorShape p_cursor_ seat_state_update_cursor(ss); } - - last_cursor_shape = p_cursor_shape; } void WaylandThread::cursor_shape_set_custom_image(DisplayServer::CursorShape p_cursor_shape, Ref<Image> p_image, const Point2i &p_hotspot) { @@ -3825,23 +3824,21 @@ void WaylandThread::cursor_shape_set_custom_image(DisplayServer::CursorShape p_c CustomCursor &cursor = custom_cursors[p_cursor_shape]; cursor.hotspot = p_hotspot; + if (cursor.wl_buffer) { + // Clean up the old Wayland buffer. + wl_buffer_destroy(cursor.wl_buffer); + } + if (cursor.buffer_data) { // Clean up the old buffer data. munmap(cursor.buffer_data, cursor.buffer_data_size); } - // NOTE: From `wl_keyboard`s of version 7 or later, the spec requires the mmap - // operation to be done with MAP_PRIVATE, as "MAP_SHARED may fail". We'll do it - // regardless of global version. - cursor.buffer_data = (uint32_t *)mmap(nullptr, data_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - - if (cursor.wl_buffer) { - // Clean up the old Wayland buffer. - wl_buffer_destroy(cursor.wl_buffer); - } + cursor.buffer_data = (uint32_t *)mmap(nullptr, data_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + cursor.buffer_data_size = data_size; // Create the Wayland buffer. - struct wl_shm_pool *wl_shm_pool = wl_shm_create_pool(registry.wl_shm, fd, image_size.height * data_size); + struct wl_shm_pool *wl_shm_pool = wl_shm_create_pool(registry.wl_shm, fd, data_size); // TODO: Make sure that WL_SHM_FORMAT_ARGB8888 format is supported. It // technically isn't garaunteed to be supported, but I think that'd be a // pretty unlikely thing to stumble upon. @@ -3869,8 +3866,6 @@ void WaylandThread::cursor_shape_clear_custom_image(DisplayServer::CursorShape p CustomCursor cursor = custom_cursors[p_cursor_shape]; custom_cursors.erase(p_cursor_shape); - current_custom_cursor = nullptr; - if (cursor.wl_buffer) { wl_buffer_destroy(cursor.wl_buffer); } diff --git a/platform/linuxbsd/wayland/wayland_thread.h b/platform/linuxbsd/wayland/wayland_thread.h index 775ca71346..819a1205d6 100644 --- a/platform/linuxbsd/wayland/wayland_thread.h +++ b/platform/linuxbsd/wayland/wayland_thread.h @@ -44,7 +44,7 @@ #include <wayland-client-core.h> #include <wayland-cursor.h> #ifdef GLES3_ENABLED -#include <wayland-egl.h> +#include <wayland-egl-core.h> #endif #include <xkbcommon/xkbcommon.h> #endif // SOWRAP_ENABLED @@ -295,7 +295,7 @@ public: }; struct PointerData { - Point2i position; + Point2 position; uint32_t motion_time = 0; // Relative motion has its own optional event and so needs its own time. @@ -305,7 +305,7 @@ public: BitField<MouseButtonMask> pressed_button_mask; MouseButton last_button_pressed = MouseButton::NONE; - Point2i last_pressed_position; + Point2 last_pressed_position; // This is needed to check for a new double click every time. bool double_click_begun = false; @@ -325,14 +325,14 @@ public: }; struct TabletToolData { - Point2i position; + Point2 position; Vector2 tilt; uint32_t pressure = 0; BitField<MouseButtonMask> pressed_button_mask; MouseButton last_button_pressed = MouseButton::NONE; - Point2i last_pressed_position; + Point2 last_pressed_position; bool double_click_begun = false; @@ -469,7 +469,6 @@ public: uint32_t *buffer_data = nullptr; uint32_t buffer_data_size = 0; - RID rid; Point2i hotspot; }; @@ -506,10 +505,8 @@ private: HashMap<DisplayServer::CursorShape, CustomCursor> custom_cursors; - struct wl_cursor *current_wl_cursor = nullptr; - struct CustomCursor *current_custom_cursor = nullptr; - - DisplayServer::CursorShape last_cursor_shape = DisplayServer::CURSOR_ARROW; + DisplayServer::CursorShape cursor_shape = DisplayServer::CURSOR_ARROW; + bool cursor_visible = true; PointerConstraint pointer_constraint = PointerConstraint::NONE; @@ -668,7 +665,7 @@ private: .preferred_buffer_transform = _wl_surface_on_preferred_buffer_transform, }; - static constexpr struct wl_callback_listener frame_wl_callback_listener { + static constexpr struct wl_callback_listener frame_wl_callback_listener = { .done = _frame_wl_callback_on_done, }; @@ -686,7 +683,7 @@ private: .name = _wl_seat_on_name, }; - static constexpr struct wl_callback_listener cursor_frame_callback_listener { + static constexpr struct wl_callback_listener cursor_frame_callback_listener = { .done = _cursor_frame_callback_on_done, }; @@ -962,7 +959,7 @@ public: DisplayServer::WindowID pointer_get_pointed_window_id() const; BitField<MouseButtonMask> pointer_get_button_mask() const; - void cursor_hide(); + void cursor_set_visible(bool p_visible); void cursor_set_shape(DisplayServer::CursorShape p_cursor_shape); void cursor_set_custom_shape(DisplayServer::CursorShape p_cursor_shape); diff --git a/platform/linuxbsd/x11/SCsub b/platform/linuxbsd/x11/SCsub index 75fe584ad5..b76b98447f 100644 --- a/platform/linuxbsd/x11/SCsub +++ b/platform/linuxbsd/x11/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index 8a2f83be2d..293623e594 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -1787,12 +1787,6 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) { _send_window_event(windows[p_id], WINDOW_EVENT_MOUSE_EXIT); } - window_set_rect_changed_callback(Callable(), p_id); - window_set_window_event_callback(Callable(), p_id); - window_set_input_event_callback(Callable(), p_id); - window_set_input_text_callback(Callable(), p_id); - window_set_drop_files_callback(Callable(), p_id); - while (wd.transient_children.size()) { window_set_transient(*wd.transient_children.begin(), INVALID_WINDOW_ID); } @@ -1836,6 +1830,12 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) { XUnmapWindow(x11_display, wd.x11_window); XDestroyWindow(x11_display, wd.x11_window); + window_set_rect_changed_callback(Callable(), p_id); + window_set_window_event_callback(Callable(), p_id); + window_set_input_event_callback(Callable(), p_id); + window_set_input_text_callback(Callable(), p_id); + window_set_drop_files_callback(Callable(), p_id); + windows.erase(p_id); } @@ -2055,7 +2055,7 @@ void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window return; } - if (window_get_mode(p_window) == WINDOW_MODE_FULLSCREEN) { + if (window_get_mode(p_window) == WINDOW_MODE_FULLSCREEN || window_get_mode(p_window) == WINDOW_MODE_MAXIMIZED) { Point2i position = screen_get_position(p_screen); Size2i size = screen_get_size(p_screen); @@ -3046,7 +3046,7 @@ void DisplayServerX11::window_set_ime_active(const bool p_active, WindowID p_win XWindowAttributes xwa; XSync(x11_display, False); XGetWindowAttributes(x11_display, wd.x11_xim_window, &xwa); - if (xwa.map_state == IsViewable) { + if (xwa.map_state == IsViewable && _window_focus_check()) { _set_input_focus(wd.x11_xim_window, RevertToParent); } XSetICFocus(wd.xic); @@ -4315,7 +4315,7 @@ bool DisplayServerX11::_window_focus_check() { bool has_focus = false; for (const KeyValue<int, DisplayServerX11::WindowData> &wid : windows) { - if (wid.value.x11_window == focused_window) { + if (wid.value.x11_window == focused_window || (wid.value.xic && wid.value.ime_active && wid.value.x11_xim_window == focused_window)) { has_focus = true; break; } @@ -5428,25 +5428,6 @@ Vector<String> DisplayServerX11::get_rendering_drivers_func() { DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error) { DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, p_context, r_error)); - if (r_error != OK) { - if (p_rendering_driver == "vulkan") { - String executable_name = OS::get_singleton()->get_executable_path().get_file(); - OS::get_singleton()->alert( - vformat("Your video card drivers seem not to support the required Vulkan version.\n\n" - "If possible, consider updating your video card drivers or using the OpenGL 3 driver.\n\n" - "You can enable the OpenGL 3 driver by starting the engine from the\n" - "command line with the command:\n\n \"%s\" --rendering-driver opengl3\n\n" - "If you recently updated your video card drivers, try rebooting.", - executable_name), - "Unable to initialize Vulkan video driver"); - } else { - OS::get_singleton()->alert( - "Your video card drivers seem not to support the required OpenGL 3.3 version.\n\n" - "If possible, consider updating your video card drivers.\n\n" - "If you recently updated your video card drivers, try rebooting.", - "Unable to initialize OpenGL video driver"); - } - } return ds; } @@ -6160,25 +6141,48 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode rendering_driver = p_rendering_driver; bool driver_found = false; + String executable_name = OS::get_singleton()->get_executable_path().get_file(); + + // Initialize context and rendering device. + #if defined(RD_ENABLED) #if defined(VULKAN_ENABLED) if (rendering_driver == "vulkan") { rendering_context = memnew(RenderingContextDriverVulkanX11); } -#endif +#endif // VULKAN_ENABLED if (rendering_context) { if (rendering_context->initialize() != OK) { - ERR_PRINT(vformat("Could not initialize %s", rendering_driver)); memdelete(rendering_context); rendering_context = nullptr; - r_error = ERR_CANT_CREATE; - return; + bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3"); + if (fallback_to_opengl3 && rendering_driver != "opengl3") { + WARN_PRINT("Your video card drivers seem not to support the required Vulkan version, switching to OpenGL 3."); + rendering_driver = "opengl3"; + OS::get_singleton()->set_current_rendering_method("gl_compatibility"); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); + } else { + r_error = ERR_CANT_CREATE; + + if (p_rendering_driver == "vulkan") { + OS::get_singleton()->alert( + vformat("Your video card drivers seem not to support the required Vulkan version.\n\n" + "If possible, consider updating your video card drivers or using the OpenGL 3 driver.\n\n" + "You can enable the OpenGL 3 driver by starting the engine from the\n" + "command line with the command:\n\n \"%s\" --rendering-driver opengl3\n\n" + "If you recently updated your video card drivers, try rebooting.", + executable_name), + "Unable to initialize Vulkan video driver"); + } + + ERR_FAIL_MSG(vformat("Could not initialize %s", rendering_driver)); + } } driver_found = true; } -#endif - // Initialize context and rendering device. +#endif // RD_ENABLED + #if defined(GLES3_ENABLED) if (rendering_driver == "opengl3" || rendering_driver == "opengl3_es") { if (getenv("DRI_PRIME") == nullptr) { @@ -6231,8 +6235,19 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode if (fallback) { WARN_PRINT("Your video card drivers seem not to support the required OpenGL version, switching to OpenGLES."); rendering_driver = "opengl3_es"; + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); } else { r_error = ERR_UNAVAILABLE; + + OS::get_singleton()->alert( + vformat("Your video card drivers seem not to support the required OpenGL 3.3 version.\n\n" + "If possible, consider updating your video card drivers or using the Vulkan driver.\n\n" + "You can enable the Vulkan driver by starting the engine from the\n" + "command line with the command:\n\n \"%s\" --rendering-driver vulkan\n\n" + "If you recently updated your video card drivers, try rebooting.", + executable_name), + "Unable to initialize OpenGL video driver"); + ERR_FAIL_MSG("Could not initialize OpenGL."); } } else { @@ -6243,20 +6258,28 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode if (rendering_driver == "opengl3_es") { gl_manager_egl = memnew(GLManagerEGL_X11); - if (gl_manager_egl->initialize() != OK) { + if (gl_manager_egl->initialize() != OK || gl_manager_egl->open_display(x11_display) != OK) { memdelete(gl_manager_egl); gl_manager_egl = nullptr; r_error = ERR_UNAVAILABLE; - ERR_FAIL_MSG("Could not initialize OpenGLES."); + + OS::get_singleton()->alert( + "Your video card drivers seem not to support the required OpenGL ES 3.0 version.\n\n" + "If possible, consider updating your video card drivers.\n\n" + "If you recently updated your video card drivers, try rebooting.", + "Unable to initialize OpenGL ES video driver"); + + ERR_FAIL_MSG("Could not initialize OpenGL ES."); } driver_found = true; RasterizerGLES3::make_current(false); } -#endif +#endif // GLES3_ENABLED + if (!driver_found) { r_error = ERR_UNAVAILABLE; - ERR_FAIL_MSG("Video driver not found"); + ERR_FAIL_MSG("Video driver not found."); } Point2i window_position; @@ -6297,7 +6320,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode RendererCompositorRD::make_current(); } -#endif +#endif // RD_ENABLED { //set all event master mask @@ -6450,7 +6473,8 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on")); portal_desktop = memnew(FreeDesktopPortalDesktop); -#endif +#endif // DBUS_ENABLED + XSetErrorHandler(&default_window_error_handler); r_error = OK; diff --git a/platform/linuxbsd/x11/gl_manager_x11_egl.h b/platform/linuxbsd/x11/gl_manager_x11_egl.h index b9c96619c4..405dda3d83 100644 --- a/platform/linuxbsd/x11/gl_manager_x11_egl.h +++ b/platform/linuxbsd/x11/gl_manager_x11_egl.h @@ -52,8 +52,8 @@ private: public: void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) {} - GLManagerEGL_X11(){}; - ~GLManagerEGL_X11(){}; + GLManagerEGL_X11() {} + ~GLManagerEGL_X11() {} }; #endif // X11_ENABLED && GLES3_ENABLED diff --git a/platform/linuxbsd/x11/rendering_context_driver_vulkan_x11.cpp b/platform/linuxbsd/x11/rendering_context_driver_vulkan_x11.cpp index bf44062266..cbcf07852b 100644 --- a/platform/linuxbsd/x11/rendering_context_driver_vulkan_x11.cpp +++ b/platform/linuxbsd/x11/rendering_context_driver_vulkan_x11.cpp @@ -32,11 +32,7 @@ #include "rendering_context_driver_vulkan_x11.h" -#ifdef USE_VOLK -#include <volk.h> -#else -#include <vulkan/vulkan.h> -#endif +#include "drivers/vulkan/godot_vulkan.h" const char *RenderingContextDriverVulkanX11::_get_platform_surface_extension() const { return VK_KHR_XLIB_SURFACE_EXTENSION_NAME; @@ -51,7 +47,7 @@ RenderingContextDriver::SurfaceID RenderingContextDriverVulkanX11::surface_creat create_info.window = wpd->window; VkSurfaceKHR vk_surface = VK_NULL_HANDLE; - VkResult err = vkCreateXlibSurfaceKHR(instance_get(), &create_info, nullptr, &vk_surface); + VkResult err = vkCreateXlibSurfaceKHR(instance_get(), &create_info, get_allocation_callbacks(VK_OBJECT_TYPE_SURFACE_KHR), &vk_surface); ERR_FAIL_COND_V(err != VK_SUCCESS, SurfaceID()); Surface *surface = memnew(Surface); |