From 92f6c34d10de3f15e214ce3e7604651f3bada446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gergely=20Kis=C2=A0?= Date: Thu, 4 Jul 2024 01:59:31 +0200 Subject: [PATCH] LibGodot Feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Based on top of the GDExtensionLoader PR: https://github.com/godotengine/godot/pull/91166 * Add a new GodotInstance GDCLASS that provides startup and iteration commands to control a Godot instance. * Adds a libgodot_create_godot_instance entry point that creates a new Godot instance and returns a GodotInstance object. * Adds a libgodot_destroy_godot_instance entry point that destroys the Godot instance. * Allow specifying an external native rendering surface handle to render Godot into the UI of a host application. * It is also possible to embed multiple Godot windows into the UI of a host application. * Currently supported on MacOS and iOS Sample Apps: https://github.com/migeran/libgodot_project Developed by [Migeran](https://migeran.com) Sponsors & Acknowledgements: * Initial development sponsored by [Smirk Software](https://www.smirk.gg/) * Rebasing to Godot 4.3 and further development sponsored by [Xibbon Inc.](https://xibbon.com) * The GDExtension registration of the host process & build system changes were based on @Faolan-Rad's LibGodot PR: https://github.com/godotengine/godot/pull/72883 Co-Authored-By: Gabor Koncz --- SConstruct | 22 +- core/config/project_settings.cpp | 5 + .../extension/gdextension_function_loader.cpp | 71 +++ core/extension/gdextension_function_loader.h | 58 ++ core/extension/gdextension_manager.cpp | 11 +- core/extension/gdextension_manager.h | 4 + core/extension/godot_instance.cpp | 81 +++ .../extension/godot_instance.h | 39 +- core/extension/libgodot.h | 69 +++ core/register_core_types.cpp | 3 + core/variant/native_ptr.h | 1 + drivers/SCsub | 1 + drivers/apple/SCsub | 6 + .../apple/rendering_native_surface_apple.cpp | 62 ++ .../apple/rendering_native_surface_apple.h | 60 ++ .../d3d12/rendering_context_driver_d3d12.cpp | 7 +- .../d3d12/rendering_context_driver_d3d12.h | 7 +- drivers/register_driver_types.cpp | 7 + .../rendering_context_driver_vulkan.cpp | 11 +- .../vulkan/rendering_context_driver_vulkan.h | 2 +- ...ndering_context_driver_vulkan_moltenvk.cpp | 28 +- ...rendering_context_driver_vulkan_moltenvk.h | 28 +- .../rendering_native_surface_vulkan.cpp | 71 +++ .../vulkan/rendering_native_surface_vulkan.h | 54 +- main/main.cpp | 10 + platform/SCsub | 10 + platform/android/SCsub | 1 + platform/android/api/api.cpp | 10 + platform/android/api/api.h | 2 + platform/android/display_server_android.cpp | 40 +- ...endering_context_driver_vulkan_android.cpp | 14 +- .../rendering_context_driver_vulkan_android.h | 6 +- .../rendering_native_surface_android.cpp | 65 +++ .../rendering_native_surface_android.h | 61 ++ platform/ios/SCsub | 38 +- platform/ios/api/api.cpp | 12 + platform/ios/api/api.h | 2 + platform/ios/detect.py | 3 + platform/ios/display_server_ios.h | 1 - platform/ios/display_server_ios.mm | 12 +- platform/ios/ios.mm | 4 + platform/ios/joypad_ios.mm | 1 - platform/ios/libgodot_ios.mm | 69 +++ platform/ios/os_ios.h | 2 +- platform/ios/os_ios.mm | 17 +- platform/linuxbsd/SCsub | 13 +- platform/linuxbsd/api/api.cpp | 64 +++ platform/linuxbsd/api/api.h | 39 ++ platform/linuxbsd/libgodot_linuxbsd.cpp | 70 +++ platform/linuxbsd/wayland/SCsub | 1 + .../wayland/display_server_wayland.cpp | 76 +-- .../linuxbsd/wayland/display_server_wayland.h | 2 +- ...endering_context_driver_vulkan_wayland.cpp | 17 +- .../rendering_context_driver_vulkan_wayland.h | 7 +- .../rendering_native_surface_wayland.cpp | 67 +++ .../rendering_native_surface_wayland.h | 64 +++ platform/linuxbsd/x11/SCsub | 1 + platform/linuxbsd/x11/display_server_x11.cpp | 47 +- .../rendering_context_driver_vulkan_x11.cpp | 17 +- .../x11/rendering_context_driver_vulkan_x11.h | 9 +- .../x11/rendering_native_surface_x11.cpp | 67 +++ .../x11/rendering_native_surface_x11.h | 66 +++ platform/macos/SCsub | 19 +- platform/macos/display_server_macos.h | 2 +- platform/macos/display_server_macos.mm | 53 +- platform/macos/libgodot_macos.mm | 72 +++ platform/register_platform_apis.h | 2 + platform/web/api/api.cpp | 6 + platform/web/api/api.h | 2 + platform/windows/SCsub | 54 +- platform/windows/api/api.cpp | 51 ++ platform/windows/api/api.h | 39 ++ platform/windows/detect.py | 2 +- platform/windows/display_server_windows.cpp | 74 ++- ...endering_context_driver_vulkan_windows.cpp | 15 +- .../rendering_context_driver_vulkan_windows.h | 11 +- .../rendering_native_surface_windows.cpp | 69 +++ .../rendering_native_surface_windows.h | 83 +++ scene/main/window.cpp | 52 ++ scene/main/window.h | 5 + servers/SCsub | 1 + servers/display_server.cpp | 12 + servers/display_server.h | 7 +- servers/display_server_embedded.cpp | 540 ++++++++++++++++++ servers/display_server_embedded.h | 194 +++++++ servers/register_server_types.cpp | 15 +- servers/register_server_types.h | 3 + .../rendering/rendering_context_driver.cpp | 12 +- servers/rendering/rendering_context_driver.h | 6 +- .../rendering/rendering_native_surface.cpp | 40 ++ servers/rendering/rendering_native_surface.h | 51 ++ 91 files changed, 2854 insertions(+), 353 deletions(-) create mode 100644 core/extension/gdextension_function_loader.cpp create mode 100644 core/extension/gdextension_function_loader.h create mode 100644 core/extension/godot_instance.cpp rename platform/macos/rendering_context_driver_vulkan_macos.h => core/extension/godot_instance.h (74%) create mode 100644 core/extension/libgodot.h create mode 100644 drivers/apple/SCsub create mode 100644 drivers/apple/rendering_native_surface_apple.cpp create mode 100644 drivers/apple/rendering_native_surface_apple.h rename platform/ios/rendering_context_driver_vulkan_ios.mm => drivers/vulkan/rendering_context_driver_vulkan_moltenvk.cpp (70%) rename platform/ios/rendering_context_driver_vulkan_ios.h => drivers/vulkan/rendering_context_driver_vulkan_moltenvk.h (80%) create mode 100644 drivers/vulkan/rendering_native_surface_vulkan.cpp rename platform/macos/rendering_context_driver_vulkan_macos.mm => drivers/vulkan/rendering_native_surface_vulkan.h (66%) create mode 100644 platform/android/rendering_native_surface_android.cpp create mode 100644 platform/android/rendering_native_surface_android.h create mode 100644 platform/ios/libgodot_ios.mm create mode 100644 platform/linuxbsd/api/api.cpp create mode 100644 platform/linuxbsd/api/api.h create mode 100644 platform/linuxbsd/libgodot_linuxbsd.cpp create mode 100644 platform/linuxbsd/wayland/rendering_native_surface_wayland.cpp create mode 100644 platform/linuxbsd/wayland/rendering_native_surface_wayland.h create mode 100644 platform/linuxbsd/x11/rendering_native_surface_x11.cpp create mode 100644 platform/linuxbsd/x11/rendering_native_surface_x11.h create mode 100644 platform/macos/libgodot_macos.mm create mode 100644 platform/windows/api/api.cpp create mode 100644 platform/windows/api/api.h create mode 100644 platform/windows/rendering_native_surface_windows.cpp create mode 100644 platform/windows/rendering_native_surface_windows.h create mode 100644 servers/display_server_embedded.cpp create mode 100644 servers/display_server_embedded.h create mode 100644 servers/rendering/rendering_native_surface.cpp create mode 100644 servers/rendering/rendering_native_surface.h diff --git a/SConstruct b/SConstruct index 3fabc4706f18..a001375e4b22 100644 --- a/SConstruct +++ b/SConstruct @@ -162,7 +162,6 @@ env.__class__.use_windows_spawn_fix = methods.use_windows_spawn_fix env.__class__.add_shared_library = methods.add_shared_library env.__class__.add_library = methods.add_library -env.__class__.add_program = methods.add_program env.__class__.CommandNoCache = methods.CommandNoCache env.__class__.Run = methods.Run env.__class__.disable_warnings = methods.disable_warnings @@ -226,6 +225,14 @@ opts.Add("custom_modules", "A list of comma-separated directory paths containing opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True)) # Advanced options +opts.Add( + EnumVariable( + "library_type", + "Build library type", + "executable", + ("executable", "static_library", "shared_library"), + ) +) opts.Add(BoolVariable("dev_mode", "Alias for dev options: verbose=yes warnings=extra werror=yes tests=yes", False)) opts.Add(BoolVariable("tests", "Build the unit tests", False)) opts.Add(BoolVariable("fast_unsafe", "Enable unsafe options for faster rebuilds", False)) @@ -317,7 +324,18 @@ if env["import_env_vars"]: if env.scons_version < (4, 3) and not env["platform"]: env["platform"] = env["p"] -if env["platform"] == "": +if env["library_type"] == "static_library": + env.Append(CPPDEFINES=["LIBRARY_ENABLED"]) +elif env["library_type"] == "shared_library": + env.Append(CPPDEFINES=["LIBRARY_ENABLED"]) + env.Append(CCFLAGS=["-fPIC"]) + env.Append(STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME=True) +else: + env.__class__.add_program = methods.add_program + +if env["platform"] != "": + selected_platform = env["platform"] +else: # Missing `platform` argument, try to detect platform automatically if ( sys.platform.startswith("linux") diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 768540a0fa1a..3da5016ea725 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -88,6 +88,11 @@ const PackedStringArray ProjectSettings::get_required_features() { // Returns the features supported by this build of Godot. Includes all required features. const PackedStringArray ProjectSettings::_get_supported_features() { PackedStringArray features = get_required_features(); + +#ifdef LIBRARY_ENABLED + features.append("LibGodot"); +#endif + #ifdef MODULE_MONO_ENABLED features.append("C#"); #endif diff --git a/core/extension/gdextension_function_loader.cpp b/core/extension/gdextension_function_loader.cpp new file mode 100644 index 000000000000..4891e6c35789 --- /dev/null +++ b/core/extension/gdextension_function_loader.cpp @@ -0,0 +1,71 @@ +/**************************************************************************/ +/* gdextension_function_loader.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "gdextension_function_loader.h" +#include "core/config/project_settings.h" +#include "gdextension.h" + +Error GDExtensionFunctionLoader::open_library(const String &p_path) { + ERR_FAIL_COND_V_MSG(!p_path.begins_with("libgodot://"), ERR_FILE_NOT_FOUND, "Function based GDExtensions should have a path starting with libgodot://"); + ERR_FAIL_COND_V_MSG(!initialization_function, ERR_DOES_NOT_EXIST, "Initialization function is required for function based GDExtensions."); + + library_path = p_path; + + return OK; +} + +Error GDExtensionFunctionLoader::initialize(GDExtensionInterfaceGetProcAddress p_get_proc_address, const Ref &p_extension, GDExtensionInitialization *r_initialization) { + ERR_FAIL_COND_V_MSG(!initialization_function, ERR_DOES_NOT_EXIST, "Initialization function is required for function based GDExtensions."); + GDExtensionBool ret = initialization_function(p_get_proc_address, p_extension.ptr(), r_initialization); + + if (ret) { + return OK; + } else { + ERR_PRINT("GDExtension initialization function for '" + library_path + "' returned an error."); + return FAILED; + } +} + +void GDExtensionFunctionLoader::close_library() { + initialization_function = nullptr; + library_path.clear(); +} + +bool GDExtensionFunctionLoader::is_library_open() const { + return !library_path.is_empty(); +} + +bool GDExtensionFunctionLoader::has_library_changed() const { + return false; +} + +void GDExtensionFunctionLoader::set_initialization_function(GDExtensionInitializationFunction p_initialization_function) { + initialization_function = p_initialization_function; +} diff --git a/core/extension/gdextension_function_loader.h b/core/extension/gdextension_function_loader.h new file mode 100644 index 000000000000..732ace6cb76a --- /dev/null +++ b/core/extension/gdextension_function_loader.h @@ -0,0 +1,58 @@ +/**************************************************************************/ +/* gdextension_function_loader.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef GDEXTENSION_FUNCTION_LOADER_H +#define GDEXTENSION_FUNCTION_LOADER_H + +#include "core/extension/gdextension_loader.h" +#include "core/os/shared_object.h" +#include + +class GDExtension; + +class GDExtensionFunctionLoader : public GDExtensionLoader { + friend class GDExtensionManager; + friend class GDExtension; + +private: + String library_path; + GDExtensionInitializationFunction initialization_function = nullptr; + +public: + Error open_library(const String &p_path) override; + Error initialize(GDExtensionInterfaceGetProcAddress p_get_proc_address, const Ref &p_extension, GDExtensionInitialization *r_initialization) override; + void close_library() override; + bool is_library_open() const override; + bool has_library_changed() const override; + + void set_initialization_function(GDExtensionInitializationFunction initialization_function); +}; + +#endif // GDEXTENSION_FUNCTION_LOADER_H diff --git a/core/extension/gdextension_manager.cpp b/core/extension/gdextension_manager.cpp index eeae6b19961b..49f7a6994efa 100644 --- a/core/extension/gdextension_manager.cpp +++ b/core/extension/gdextension_manager.cpp @@ -31,6 +31,7 @@ #include "gdextension_manager.h" #include "core/extension/gdextension_compat_hashes.h" +#include "core/extension/gdextension_function_loader.h" #include "core/extension/gdextension_library_loader.h" #include "core/io/file_access.h" #include "core/object/script_language.h" @@ -72,7 +73,14 @@ GDExtensionManager::LoadStatus GDExtensionManager::_unload_extension_internal(co GDExtensionManager::LoadStatus GDExtensionManager::load_extension(const String &p_path) { Ref loader; loader.instantiate(); - return GDExtensionManager::get_singleton()->load_extension_with_loader(p_path, loader); + return load_extension_with_loader(p_path, loader); +} + +GDExtensionManager::LoadStatus GDExtensionManager::load_function_extension(const String &p_path, GDExtensionConstPtr p_init_func) { + Ref func_loader; + func_loader.instantiate(); + func_loader->set_initialization_function((GDExtensionInitializationFunction) * (p_init_func.data)); + return load_extension_with_loader(p_path, func_loader); } GDExtensionManager::LoadStatus GDExtensionManager::load_extension_with_loader(const String &p_path, const Ref &p_loader) { @@ -280,6 +288,7 @@ GDExtensionManager *GDExtensionManager::get_singleton() { void GDExtensionManager::_bind_methods() { ClassDB::bind_method(D_METHOD("load_extension", "path"), &GDExtensionManager::load_extension); + ClassDB::bind_method(D_METHOD("load_function_extension", "path", "init_func"), &GDExtensionManager::load_function_extension); ClassDB::bind_method(D_METHOD("reload_extension", "path"), &GDExtensionManager::reload_extension); ClassDB::bind_method(D_METHOD("unload_extension", "path"), &GDExtensionManager::unload_extension); ClassDB::bind_method(D_METHOD("is_extension_loaded", "path"), &GDExtensionManager::is_extension_loaded); diff --git a/core/extension/gdextension_manager.h b/core/extension/gdextension_manager.h index b48818960483..0853d6b05432 100644 --- a/core/extension/gdextension_manager.h +++ b/core/extension/gdextension_manager.h @@ -32,6 +32,9 @@ #define GDEXTENSION_MANAGER_H #include "core/extension/gdextension.h" +#include "core/variant/native_ptr.h" + +GDVIRTUAL_NATIVE_PTR(GDExtensionInitializationFunction) class GDExtensionManager : public Object { GDCLASS(GDExtensionManager, Object); @@ -63,6 +66,7 @@ class GDExtensionManager : public Object { public: LoadStatus load_extension(const String &p_path); + LoadStatus load_function_extension(const String &p_path, GDExtensionConstPtr p_init_func); LoadStatus load_extension_with_loader(const String &p_path, const Ref &p_loader); LoadStatus reload_extension(const String &p_path); LoadStatus unload_extension(const String &p_path); diff --git a/core/extension/godot_instance.cpp b/core/extension/godot_instance.cpp new file mode 100644 index 000000000000..69c1fb8d0d5c --- /dev/null +++ b/core/extension/godot_instance.cpp @@ -0,0 +1,81 @@ +/**************************************************************************/ +/* godot_instance.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "godot_instance.h" +#include "core/extension/gdextension_manager.h" +#include "main/main.h" +#include "servers/display_server.h" + +void GodotInstance::_bind_methods() { + ClassDB::bind_method(D_METHOD("start"), &GodotInstance::start); + ClassDB::bind_method(D_METHOD("is_started"), &GodotInstance::is_started); + ClassDB::bind_method(D_METHOD("iteration"), &GodotInstance::iteration); +} + +GodotInstance::GodotInstance() { +} + +GodotInstance::~GodotInstance() { +} + +bool GodotInstance::initialize(GDExtensionInitializationFunction p_init_func) { + GDExtensionManager *gdextension_manager = GDExtensionManager::get_singleton(); + GDExtensionConstPtr ptr((const GDExtensionInitializationFunction *)&p_init_func); + GDExtensionManager::LoadStatus status = gdextension_manager->load_function_extension("libgodot://main", ptr); + return status == GDExtensionManager::LoadStatus::LOAD_STATUS_OK; +} + +bool GodotInstance::start() { + Error err = Main::setup2(); + if (err != OK) { + return false; + } + started = Main::start() == EXIT_SUCCESS; + if (started) { + OS::get_singleton()->get_main_loop()->initialize(); + } + return started; +} + +bool GodotInstance::is_started() { + return started; +} + +bool GodotInstance::iteration() { + DisplayServer::get_singleton()->process_events(); + return Main::iteration(); +} + +void GodotInstance::stop() { + if (started) { + OS::get_singleton()->get_main_loop()->finalize(); + } + started = false; +} diff --git a/platform/macos/rendering_context_driver_vulkan_macos.h b/core/extension/godot_instance.h similarity index 74% rename from platform/macos/rendering_context_driver_vulkan_macos.h rename to core/extension/godot_instance.h index 32f8891a2ea1..3695a75e85e9 100644 --- a/platform/macos/rendering_context_driver_vulkan_macos.h +++ b/core/extension/godot_instance.h @@ -1,5 +1,5 @@ /**************************************************************************/ -/* rendering_context_driver_vulkan_macos.h */ +/* godot_instance.h */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,31 +28,30 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef RENDERING_CONTEXT_DRIVER_VULKAN_MACOS_H -#define RENDERING_CONTEXT_DRIVER_VULKAN_MACOS_H +#ifndef GODOT_INSTANCE_H +#define GODOT_INSTANCE_H -#ifdef VULKAN_ENABLED +#include "core/extension/gdextension_interface.h" +#include "core/object/class_db.h" +#include "core/object/object.h" -#include "drivers/vulkan/rendering_context_driver_vulkan.h" +class GodotInstance : public Object { + GDCLASS(GodotInstance, Object); -#import + static void _bind_methods(); -class RenderingContextDriverVulkanMacOS : public RenderingContextDriverVulkan { -private: - virtual const char *_get_platform_surface_extension() const override final; - -protected: - SurfaceID surface_create(const void *p_platform_data) override final; + bool started = false; public: - struct WindowPlatformData { - CAMetalLayer *const *layer_ptr; - }; + GodotInstance(); + ~GodotInstance(); - RenderingContextDriverVulkanMacOS(); - ~RenderingContextDriverVulkanMacOS(); -}; + bool initialize(GDExtensionInitializationFunction p_init_func); -#endif // VULKAN_ENABLED + bool start(); + bool is_started(); + bool iteration(); + void stop(); +}; -#endif // RENDERING_CONTEXT_DRIVER_VULKAN_MACOS_H +#endif // GODOT_INSTANCE_H diff --git a/core/extension/libgodot.h b/core/extension/libgodot.h new file mode 100644 index 000000000000..acb30c08c51b --- /dev/null +++ b/core/extension/libgodot.h @@ -0,0 +1,69 @@ +/**************************************************************************/ +/* libgodot.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef LIBGODOT_H +#define LIBGODOT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gdextension_interface.h" + +/** + * @name libgodot_create_godot_instance + * @since 4.4 + * + * Creates a new Godot instance. + * + * @param p_argc The number of command line arguments. + * @param p_argv The C-style array of command line arguments. + * @param p_init_func GDExtension initialization function of the host application. + * + * @return A pointer to created \ref GodotInstance GDExtension object or nullptr if there was an error. + */ +GDExtensionObjectPtr libgodot_create_godot_instance(int p_argc, char *p_argv[], GDExtensionInitializationFunction p_init_func); + +/** + * @name libgodot_destroy_godot_instance + * @since 4.4 + * + * Destroys an existing Godot instance. + * + * @param p_godot_instance The reference to the GodotInstance object to destroy. + * + */ +void libgodot_destroy_godot_instance(GDExtensionObjectPtr p_godot_instance); + +#ifdef __cplusplus +} +#endif + +#endif // LIBGODOT_H diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index c0a86e9fb734..c7b1b1380ea4 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -39,6 +39,7 @@ #include "core/debugger/engine_profiler.h" #include "core/extension/gdextension.h" #include "core/extension/gdextension_manager.h" +#include "core/extension/godot_instance.h" #include "core/input/input.h" #include "core/input/input_map.h" #include "core/input/shortcut.h" @@ -266,6 +267,8 @@ void register_core_types() { GDREGISTER_CLASS(GDExtension); + GDREGISTER_ABSTRACT_CLASS(GodotInstance); + GDREGISTER_ABSTRACT_CLASS(GDExtensionManager); GDREGISTER_ABSTRACT_CLASS(ResourceUID); diff --git a/core/variant/native_ptr.h b/core/variant/native_ptr.h index 33ba03813271..aeb24500dd5f 100644 --- a/core/variant/native_ptr.h +++ b/core/variant/native_ptr.h @@ -32,6 +32,7 @@ #define NATIVE_PTR_H #include "core/math/audio_frame.h" +#include "core/variant/binder_common.h" #include "core/variant/method_ptrcall.h" #include "core/variant/type_info.h" diff --git a/drivers/SCsub b/drivers/SCsub index e77b96cc87d8..42911f527bea 100644 --- a/drivers/SCsub +++ b/drivers/SCsub @@ -25,6 +25,7 @@ SConscript("coremidi/SCsub") SConscript("winmidi/SCsub") # Graphics drivers +SConscript("apple/SCsub") if env["vulkan"]: SConscript("vulkan/SCsub") if env["d3d12"]: diff --git a/drivers/apple/SCsub b/drivers/apple/SCsub new file mode 100644 index 000000000000..4e1b5f2a3624 --- /dev/null +++ b/drivers/apple/SCsub @@ -0,0 +1,6 @@ +#!/usr/bin/env python + +Import("env") + +# Driver source files +env.add_source_files(env.drivers_sources, "*.cpp") diff --git a/drivers/apple/rendering_native_surface_apple.cpp b/drivers/apple/rendering_native_surface_apple.cpp new file mode 100644 index 000000000000..7cedf959b4ba --- /dev/null +++ b/drivers/apple/rendering_native_surface_apple.cpp @@ -0,0 +1,62 @@ +/**************************************************************************/ +/* rendering_native_surface_apple.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "rendering_native_surface_apple.h" +#include "drivers/vulkan/rendering_context_driver_vulkan_moltenvk.h" + +void RenderingNativeSurfaceApple::_bind_methods() { + ClassDB::bind_static_method("RenderingNativeSurfaceApple", D_METHOD("create", "layer"), &RenderingNativeSurfaceApple::create_api); +} + +Ref RenderingNativeSurfaceApple::create_api(/* GDExtensionConstPtr */ uint64_t p_layer) { + return RenderingNativeSurfaceApple::create((void *)p_layer /* .operator const void *() */); +} + +Ref RenderingNativeSurfaceApple::create(void *p_layer) { + Ref result = memnew(RenderingNativeSurfaceApple); + result->layer = p_layer; + return result; +} + +RenderingContextDriver *RenderingNativeSurfaceApple::create_rendering_context() { +#ifdef __APPLE__ + return memnew(RenderingContextDriverVulkanMoltenVk); +#else + return nullptr; +#endif +} + +RenderingNativeSurfaceApple::RenderingNativeSurfaceApple() { + // Does nothing. +} + +RenderingNativeSurfaceApple::~RenderingNativeSurfaceApple() { + // Does nothing. +} diff --git a/drivers/apple/rendering_native_surface_apple.h b/drivers/apple/rendering_native_surface_apple.h new file mode 100644 index 000000000000..9eb4fd059f6c --- /dev/null +++ b/drivers/apple/rendering_native_surface_apple.h @@ -0,0 +1,60 @@ +/**************************************************************************/ +/* rendering_native_surface_apple.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef RENDERING_NATIVE_SURFACE_APPLE_H +#define RENDERING_NATIVE_SURFACE_APPLE_H + +#include "core/variant/native_ptr.h" +#include "servers/rendering/rendering_native_surface.h" + +class RenderingNativeSurfaceApple : public RenderingNativeSurface { + GDCLASS(RenderingNativeSurfaceApple, RenderingNativeSurface); + + static void _bind_methods(); + + void *layer = nullptr; + +public: + // TODO: Remove workaround when SwiftGodot starts to support const void * arguments. + static Ref create_api(/* GDExtensionConstPtr */ uint64_t p_layer); + + static Ref create(void *p_layer); + + void *get_metal_layer() const { + return layer; + }; + + RenderingContextDriver *create_rendering_context() override; + + RenderingNativeSurfaceApple(); + ~RenderingNativeSurfaceApple(); +}; + +#endif // RENDERING_NATIVE_SURFACE_APPLE_H diff --git a/drivers/d3d12/rendering_context_driver_d3d12.cpp b/drivers/d3d12/rendering_context_driver_d3d12.cpp index c4cb99fcaafd..bec3483a9866 100644 --- a/drivers/d3d12/rendering_context_driver_d3d12.cpp +++ b/drivers/d3d12/rendering_context_driver_d3d12.cpp @@ -253,10 +253,11 @@ void RenderingContextDriverD3D12::driver_free(RenderingDeviceDriver *p_driver) { memdelete(p_driver); } -RenderingContextDriver::SurfaceID RenderingContextDriverD3D12::surface_create(const void *p_platform_data) { - const WindowPlatformData *wpd = (const WindowPlatformData *)(p_platform_data); +RenderingContextDriver::SurfaceID RenderingContextDriverD3D12::surface_create(Ref p_native_surface) { + Ref windows_native_surface = Object::cast_to(*p_native_surface); + ERR_FAIL_COND_V(windows_native_surface.is_null(), SurfaceID()); Surface *surface = memnew(Surface); - surface->hwnd = wpd->window; + surface->hwnd = windows_native_surface->get_window_handle(); return SurfaceID(surface); } diff --git a/drivers/d3d12/rendering_context_driver_d3d12.h b/drivers/d3d12/rendering_context_driver_d3d12.h index a2d828ded1ac..92a7aa8d86e7 100644 --- a/drivers/d3d12/rendering_context_driver_d3d12.h +++ b/drivers/d3d12/rendering_context_driver_d3d12.h @@ -91,7 +91,7 @@ class RenderingContextDriverD3D12 : public RenderingContextDriver { virtual bool device_supports_present(uint32_t p_device_index, SurfaceID p_surface) const override; virtual RenderingDeviceDriver *driver_create() override; virtual void driver_free(RenderingDeviceDriver *p_driver) override; - virtual SurfaceID surface_create(const void *p_platform_data) override; + virtual SurfaceID surface_create(Ref p_native_surface) override; virtual void surface_set_size(SurfaceID p_surface, uint32_t p_width, uint32_t p_height) override; virtual void surface_set_vsync_mode(SurfaceID p_surface, DisplayServer::VSyncMode p_vsync_mode) override; virtual DisplayServer::VSyncMode surface_get_vsync_mode(SurfaceID p_surface) const override; @@ -102,11 +102,6 @@ class RenderingContextDriverD3D12 : public RenderingContextDriver { virtual void surface_destroy(SurfaceID p_surface) override; virtual bool is_debug_utils_enabled() const override; - // Platform-specific data for the Windows embedded in this driver. - struct WindowPlatformData { - HWND window; - }; - // D3D12-only methods. struct Surface { HWND hwnd = nullptr; diff --git a/drivers/register_driver_types.cpp b/drivers/register_driver_types.cpp index d5524fcc2f2d..281397129a53 100644 --- a/drivers/register_driver_types.cpp +++ b/drivers/register_driver_types.cpp @@ -31,13 +31,20 @@ #include "register_driver_types.h" #include "core/extension/gdextension_manager.h" +#include "core/object/class_db.h" #include "drivers/png/image_loader_png.h" #include "drivers/png/resource_saver_png.h" +#include "drivers/apple/rendering_native_surface_apple.h" +#include "drivers/vulkan/rendering_native_surface_vulkan.h" + static Ref image_loader_png; static Ref resource_saver_png; void register_core_driver_types() { + GDREGISTER_ABSTRACT_CLASS(RenderingNativeSurfaceApple) + GDREGISTER_ABSTRACT_CLASS(RenderingNativeSurfaceVulkan) + image_loader_png.instantiate(); ImageLoader::add_image_format_loader(image_loader_png); diff --git a/drivers/vulkan/rendering_context_driver_vulkan.cpp b/drivers/vulkan/rendering_context_driver_vulkan.cpp index 7cba82097808..292a28ecc564 100644 --- a/drivers/vulkan/rendering_context_driver_vulkan.cpp +++ b/drivers/vulkan/rendering_context_driver_vulkan.cpp @@ -31,6 +31,7 @@ #ifdef VULKAN_ENABLED #include "rendering_context_driver_vulkan.h" +#include "rendering_native_surface_vulkan.h" #include "vk_enum_string_helper.h" @@ -625,9 +626,13 @@ void RenderingContextDriverVulkan::driver_free(RenderingDeviceDriver *p_driver) memdelete(p_driver); } -RenderingContextDriver::SurfaceID RenderingContextDriverVulkan::surface_create(const void *p_platform_data) { - DEV_ASSERT(false && "Surface creation should not be called on the platform-agnostic version of the driver."); - return SurfaceID(); +RenderingContextDriver::SurfaceID RenderingContextDriverVulkan::surface_create(Ref p_native_surface) { + Ref vulkan_native_surface = Object::cast_to(*p_native_surface); + ERR_FAIL_COND_V(vulkan_native_surface == nullptr, SurfaceID()); + + Surface *surface = memnew(Surface); + surface->vk_surface = vulkan_native_surface->get_vulkan_surface(); + return SurfaceID(surface); } void RenderingContextDriverVulkan::surface_set_size(SurfaceID p_surface, uint32_t p_width, uint32_t p_height) { diff --git a/drivers/vulkan/rendering_context_driver_vulkan.h b/drivers/vulkan/rendering_context_driver_vulkan.h index f1d4021e3225..f4b616db9684 100644 --- a/drivers/vulkan/rendering_context_driver_vulkan.h +++ b/drivers/vulkan/rendering_context_driver_vulkan.h @@ -126,7 +126,7 @@ class RenderingContextDriverVulkan : public RenderingContextDriver { virtual bool device_supports_present(uint32_t p_device_index, SurfaceID p_surface) const override; virtual RenderingDeviceDriver *driver_create() override; virtual void driver_free(RenderingDeviceDriver *p_driver) override; - virtual SurfaceID surface_create(const void *p_platform_data) override; + virtual SurfaceID surface_create(Ref p_native_surface) override; virtual void surface_set_size(SurfaceID p_surface, uint32_t p_width, uint32_t p_height) override; virtual void surface_set_vsync_mode(SurfaceID p_surface, DisplayServer::VSyncMode p_vsync_mode) override; virtual DisplayServer::VSyncMode surface_get_vsync_mode(SurfaceID p_surface) const override; diff --git a/platform/ios/rendering_context_driver_vulkan_ios.mm b/drivers/vulkan/rendering_context_driver_vulkan_moltenvk.cpp similarity index 70% rename from platform/ios/rendering_context_driver_vulkan_ios.mm rename to drivers/vulkan/rendering_context_driver_vulkan_moltenvk.cpp index 6a6af1bc4191..932a365bbc6f 100644 --- a/platform/ios/rendering_context_driver_vulkan_ios.mm +++ b/drivers/vulkan/rendering_context_driver_vulkan_moltenvk.cpp @@ -1,5 +1,5 @@ /**************************************************************************/ -/* rendering_context_driver_vulkan_ios.mm */ +/* rendering_context_driver_vulkan_moltenvk.cpp */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#import "rendering_context_driver_vulkan_ios.h" +#include "rendering_context_driver_vulkan_moltenvk.h" +#include "drivers/apple/rendering_native_surface_apple.h" +#include "rendering_native_surface_vulkan.h" +#ifdef __APPLE__ #ifdef VULKAN_ENABLED #ifdef USE_VOLK @@ -38,32 +41,35 @@ #include #endif -const char *RenderingContextDriverVulkanIOS::_get_platform_surface_extension() const { +const char *RenderingContextDriverVulkanMoltenVk::_get_platform_surface_extension() const { return VK_EXT_METAL_SURFACE_EXTENSION_NAME; } -RenderingContextDriver::SurfaceID RenderingContextDriverVulkanIOS::surface_create(const void *p_platform_data) { - const WindowPlatformData *wpd = (const WindowPlatformData *)(p_platform_data); +RenderingContextDriver::SurfaceID RenderingContextDriverVulkanMoltenVk::surface_create(Ref p_native_surface) { + Ref apple_native_surface = Object::cast_to(*p_native_surface); + ERR_FAIL_COND_V(apple_native_surface.is_null(), SurfaceID()); VkMetalSurfaceCreateInfoEXT create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT; - create_info.pLayer = *wpd->layer_ptr; + create_info.pLayer = apple_native_surface->get_metal_layer(); VkSurfaceKHR vk_surface = VK_NULL_HANDLE; VkResult err = vkCreateMetalSurfaceEXT(instance_get(), &create_info, nullptr, &vk_surface); ERR_FAIL_COND_V(err != VK_SUCCESS, SurfaceID()); - Surface *surface = memnew(Surface); - surface->vk_surface = vk_surface; - return SurfaceID(surface); + Ref vulkan_native_surface = RenderingNativeSurfaceVulkan::create(vk_surface); + RenderingContextDriver::SurfaceID result = RenderingContextDriverVulkan::surface_create(vulkan_native_surface); + + return result; } -RenderingContextDriverVulkanIOS::RenderingContextDriverVulkanIOS() { +RenderingContextDriverVulkanMoltenVk::RenderingContextDriverVulkanMoltenVk() { // Does nothing. } -RenderingContextDriverVulkanIOS::~RenderingContextDriverVulkanIOS() { +RenderingContextDriverVulkanMoltenVk::~RenderingContextDriverVulkanMoltenVk() { // Does nothing. } #endif // VULKAN_ENABLED +#endif // __APPLE__ diff --git a/platform/ios/rendering_context_driver_vulkan_ios.h b/drivers/vulkan/rendering_context_driver_vulkan_moltenvk.h similarity index 80% rename from platform/ios/rendering_context_driver_vulkan_ios.h rename to drivers/vulkan/rendering_context_driver_vulkan_moltenvk.h index dc85ff738dce..43914a4d2496 100644 --- a/platform/ios/rendering_context_driver_vulkan_ios.h +++ b/drivers/vulkan/rendering_context_driver_vulkan_moltenvk.h @@ -1,5 +1,5 @@ /**************************************************************************/ -/* rendering_context_driver_vulkan_ios.h */ +/* rendering_context_driver_vulkan_moltenvk.h */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,31 +28,33 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef RENDERING_CONTEXT_DRIVER_VULKAN_IOS_H -#define RENDERING_CONTEXT_DRIVER_VULKAN_IOS_H +#ifndef RENDERING_CONTEXT_DRIVER_VULKAN_MOLTENVK_H +#define RENDERING_CONTEXT_DRIVER_VULKAN_MOLTENVK_H +#ifdef __APPLE__ #ifdef VULKAN_ENABLED #include "drivers/vulkan/rendering_context_driver_vulkan.h" -#import +#ifdef __OBJC__ +@class CAMetalLayer; +#else +typedef void CAMetalLayer; +#endif -class RenderingContextDriverVulkanIOS : public RenderingContextDriverVulkan { +class RenderingContextDriverVulkanMoltenVk : public RenderingContextDriverVulkan { private: virtual const char *_get_platform_surface_extension() const override final; protected: - SurfaceID surface_create(const void *p_platform_data) override final; + SurfaceID surface_create(Ref p_native_surface) override final; public: - struct WindowPlatformData { - CAMetalLayer *const *layer_ptr; - }; - - RenderingContextDriverVulkanIOS(); - ~RenderingContextDriverVulkanIOS(); + RenderingContextDriverVulkanMoltenVk(); + ~RenderingContextDriverVulkanMoltenVk(); }; #endif // VULKAN_ENABLED +#endif // __APPLE__ -#endif // RENDERING_CONTEXT_DRIVER_VULKAN_IOS_H +#endif // RENDERING_CONTEXT_DRIVER_VULKAN_MOLTENVK_H diff --git a/drivers/vulkan/rendering_native_surface_vulkan.cpp b/drivers/vulkan/rendering_native_surface_vulkan.cpp new file mode 100644 index 000000000000..ceb639bf34ad --- /dev/null +++ b/drivers/vulkan/rendering_native_surface_vulkan.cpp @@ -0,0 +1,71 @@ +/**************************************************************************/ +/* rendering_native_surface_vulkan.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "rendering_native_surface_vulkan.h" + +#include "drivers/vulkan/rendering_context_driver_vulkan.h" + +void RenderingNativeSurfaceVulkan::_bind_methods() { + ClassDB::bind_static_method("RenderingNativeSurfaceVulkan", D_METHOD("create", "vulkan_surface"), &RenderingNativeSurfaceVulkan::create_api); +} + +Ref RenderingNativeSurfaceVulkan::create_api(GDExtensionConstPtr p_vulkan_surface) { + Ref result = nullptr; +#ifdef VULKAN_ENABLED + result = RenderingNativeSurfaceVulkan::create((VkSurfaceKHR)p_vulkan_surface.operator const void *()); +#endif + return result; +} + +#ifdef VULKAN_ENABLED + +Ref RenderingNativeSurfaceVulkan::create(VkSurfaceKHR p_vulkan_surface) { + Ref result = memnew(RenderingNativeSurfaceVulkan); + result->vulkan_surface = p_vulkan_surface; + return result; +} + +#endif + +RenderingContextDriver *RenderingNativeSurfaceVulkan::create_rendering_context() { +#if defined(VULKAN_ENABLED) + return memnew(RenderingContextDriverVulkan); +#else + return nullptr; +#endif +} + +RenderingNativeSurfaceVulkan::RenderingNativeSurfaceVulkan() { + // Does nothing. +} + +RenderingNativeSurfaceVulkan::~RenderingNativeSurfaceVulkan() { + // Does nothing. +} diff --git a/platform/macos/rendering_context_driver_vulkan_macos.mm b/drivers/vulkan/rendering_native_surface_vulkan.h similarity index 66% rename from platform/macos/rendering_context_driver_vulkan_macos.mm rename to drivers/vulkan/rendering_native_surface_vulkan.h index afefe5a6f7d4..1f0301b63d98 100644 --- a/platform/macos/rendering_context_driver_vulkan_macos.mm +++ b/drivers/vulkan/rendering_native_surface_vulkan.h @@ -1,5 +1,5 @@ /**************************************************************************/ -/* rendering_context_driver_vulkan_macos.mm */ +/* rendering_native_surface_vulkan.h */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,42 +28,44 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#include "rendering_context_driver_vulkan_macos.h" +#ifndef RENDERING_NATIVE_SURFACE_VULKAN_H +#define RENDERING_NATIVE_SURFACE_VULKAN_H -#ifdef VULKAN_ENABLED +#include "core/variant/native_ptr.h" +#include "servers/rendering/rendering_native_surface.h" +#ifdef VULKAN_ENABLED #ifdef USE_VOLK #include #else -#include +#include #endif +#endif + +class RenderingNativeSurfaceVulkan : public RenderingNativeSurface { + GDCLASS(RenderingNativeSurfaceVulkan, RenderingNativeSurface); -const char *RenderingContextDriverVulkanMacOS::_get_platform_surface_extension() const { - return VK_EXT_METAL_SURFACE_EXTENSION_NAME; -} + static void _bind_methods(); -RenderingContextDriver::SurfaceID RenderingContextDriverVulkanMacOS::surface_create(const void *p_platform_data) { - const WindowPlatformData *wpd = (const WindowPlatformData *)(p_platform_data); +#ifdef VULKAN_ENABLED + VkSurfaceKHR vulkan_surface = VK_NULL_HANDLE; +#endif - VkMetalSurfaceCreateInfoEXT create_info = {}; - create_info.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT; - create_info.pLayer = *wpd->layer_ptr; +public: + static Ref create_api(GDExtensionConstPtr vulkan_surface); - VkSurfaceKHR vk_surface = VK_NULL_HANDLE; - VkResult err = vkCreateMetalSurfaceEXT(instance_get(), &create_info, nullptr, &vk_surface); - ERR_FAIL_COND_V(err != VK_SUCCESS, SurfaceID()); +#ifdef VULKAN_ENABLED + static Ref create(VkSurfaceKHR vulkan_surface); - Surface *surface = memnew(Surface); - surface->vk_surface = vk_surface; - return SurfaceID(surface); -} + VkSurfaceKHR get_vulkan_surface() const { + return vulkan_surface; + }; +#endif -RenderingContextDriverVulkanMacOS::RenderingContextDriverVulkanMacOS() { - // Does nothing. -} + RenderingContextDriver *create_rendering_context() override; -RenderingContextDriverVulkanMacOS::~RenderingContextDriverVulkanMacOS() { - // Does nothing. -} + RenderingNativeSurfaceVulkan(); + ~RenderingNativeSurfaceVulkan(); +}; -#endif // VULKAN_ENABLED +#endif // RENDERING_NATIVE_SURFACE_VULKAN_H diff --git a/main/main.cpp b/main/main.cpp index 1cbd732747bf..58f61655eab6 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -743,6 +743,7 @@ Error Main::test_setup() { ClassDB::set_current_api(ClassDB::API_CORE); #endif + register_core_platform_apis(); register_platform_apis(); // Theme needs modules to be initialized so that sub-resources can be loaded. @@ -804,6 +805,7 @@ void Main::test_cleanup() { uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SCENE); unregister_platform_apis(); + unregister_core_platform_apis(); unregister_driver_types(); unregister_scene_types(); @@ -814,6 +816,7 @@ void Main::test_cleanup() { GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_SERVERS); uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS); unregister_server_types(); + unregister_core_server_types(); EngineDebugger::deinitialize(); OS::get_singleton()->finalize(); @@ -920,6 +923,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph register_core_types(); register_core_driver_types(); + register_core_platform_apis(); + MAIN_PRINT("Main: Initialize Globals"); input_map = memnew(InputMap); @@ -2450,6 +2455,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph message_queue = memnew(MessageQueue); + // Register Core Server Types + register_core_server_types(); + Thread::release_main_thread(); // If setup2() is called from another thread, that one will become main thread, so preventively release this one. set_current_thread_safe_for_nodes(false); @@ -2502,6 +2510,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph memdelete(packed_data); } + unregister_core_platform_apis(); unregister_core_driver_types(); unregister_core_extensions(); @@ -4296,6 +4305,7 @@ void Main::cleanup(bool p_force) { GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_SERVERS); uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS); unregister_server_types(); + unregister_core_server_types(); EngineDebugger::deinitialize(); diff --git a/platform/SCsub b/platform/SCsub index b07023efedce..d8c829de3f74 100644 --- a/platform/SCsub +++ b/platform/SCsub @@ -36,6 +36,8 @@ def register_platform_apis_builder(target, source, env): api_inc = "\n".join([f'#include "{p}/api/api.h"' for p in platforms]) api_reg = "\n".join([f"\tregister_{p}_api();" for p in platforms]) api_unreg = "\n".join([f"\tunregister_{p}_api();" for p in platforms]) + reg_core_apis = "\n".join([f"\tregister_core_{p}_api();" for p in platforms]) + unreg_core_apis = "\n".join([f"\tunregister_core_{p}_api();" for p in platforms]) with methods.generated_wrapper(target) as file: file.write( f"""\ @@ -50,6 +52,14 @@ void register_platform_apis() {{ void unregister_platform_apis() {{ {api_unreg} }} + +void register_core_platform_apis() {{ +{reg_core_apis} +}} + +void unregister_core_platform_apis() {{ +{unreg_core_apis} +}} """ ) diff --git a/platform/android/SCsub b/platform/android/SCsub index bc1b5e9200b3..148481125d58 100644 --- a/platform/android/SCsub +++ b/platform/android/SCsub @@ -27,6 +27,7 @@ android_files = [ "display_server_android.cpp", "plugin/godot_plugin_jni.cpp", "rendering_context_driver_vulkan_android.cpp", + "rendering_native_surface_android.cpp", ] env_android = env.Clone() diff --git a/platform/android/api/api.cpp b/platform/android/api/api.cpp index 60c369951c91..14ea6c5137f2 100644 --- a/platform/android/api/api.cpp +++ b/platform/android/api/api.cpp @@ -34,11 +34,21 @@ #include "jni_singleton.h" #include "core/config/engine.h" +#include "platform/android/rendering_native_surface_android.h" #if !defined(ANDROID_ENABLED) static JavaClassWrapper *java_class_wrapper = nullptr; #endif +void register_core_android_api() { +#if defined(ANDROID_ENABLED) + GDREGISTER_ABSTRACT_CLASS(RenderingNativeSurfaceAndroid); +#endif +} + +void unregister_core_android_api() { +} + void register_android_api() { #if !defined(ANDROID_ENABLED) // On Android platforms, the `java_class_wrapper` instantiation and the diff --git a/platform/android/api/api.h b/platform/android/api/api.h index c744e464d5b4..bcc9dd9e45d4 100644 --- a/platform/android/api/api.h +++ b/platform/android/api/api.h @@ -31,6 +31,8 @@ #ifndef ANDROID_API_H #define ANDROID_API_H +void register_core_android_api(); +void unregister_core_android_api(); void register_android_api(); void unregister_android_api(); diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index 06b304dcde35..f68b4391e820 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -40,10 +40,6 @@ #if defined(RD_ENABLED) #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #include "servers/rendering/rendering_device.h" - -#if defined(VULKAN_ENABLED) -#include "rendering_context_driver_vulkan_android.h" -#endif #endif #ifdef GLES3_ENABLED @@ -542,20 +538,16 @@ void DisplayServerAndroid::reset_window() { VSyncMode last_vsync_mode = rendering_context->window_get_vsync_mode(MAIN_WINDOW_ID); rendering_context->window_destroy(MAIN_WINDOW_ID); - union { -#ifdef VULKAN_ENABLED - RenderingContextDriverVulkanAndroid::WindowPlatformData vulkan; -#endif - } wpd; + Ref android_surface; #ifdef VULKAN_ENABLED if (rendering_driver == "vulkan") { ANativeWindow *native_window = OS_Android::get_singleton()->get_native_window(); ERR_FAIL_NULL(native_window); - wpd.vulkan.window = native_window; + android_surface = RenderingNativeSurfaceAndroid::create(native_window); } #endif - if (rendering_context->window_create(MAIN_WINDOW_ID, &wpd) != OK) { + if (rendering_context->window_create(MAIN_WINDOW_ID, android_surface) != OK) { ERR_PRINT(vformat("Failed to reset %s window.", rendering_driver)); memdelete(rendering_context); rendering_context = nullptr; @@ -596,12 +588,19 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis rendering_context = nullptr; rendering_device = nullptr; -#if defined(VULKAN_ENABLED) + Ref android_surface; +#ifdef VULKAN_ENABLED if (rendering_driver == "vulkan") { - rendering_context = memnew(RenderingContextDriverVulkanAndroid); + ANativeWindow *native_window = OS_Android::get_singleton()->get_native_window(); + ERR_FAIL_NULL(native_window); + android_surface = RenderingNativeSurfaceAndroid::create(native_window); } #endif + if (android_surface.is_valid()) { + rendering_context = android_surface->create_rendering_context(); + } + if (rendering_context) { if (rendering_context->initialize() != OK) { ERR_PRINT(vformat("Failed to initialize %s context", rendering_driver)); @@ -611,20 +610,7 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis return; } - union { -#ifdef VULKAN_ENABLED - RenderingContextDriverVulkanAndroid::WindowPlatformData vulkan; -#endif - } wpd; -#ifdef VULKAN_ENABLED - if (rendering_driver == "vulkan") { - ANativeWindow *native_window = OS_Android::get_singleton()->get_native_window(); - ERR_FAIL_NULL(native_window); - wpd.vulkan.window = native_window; - } -#endif - - if (rendering_context->window_create(MAIN_WINDOW_ID, &wpd) != OK) { + if (rendering_context->window_create(MAIN_WINDOW_ID, android_surface) != OK) { ERR_PRINT(vformat("Failed to create %s window.", rendering_driver)); memdelete(rendering_context); rendering_context = nullptr; diff --git a/platform/android/rendering_context_driver_vulkan_android.cpp b/platform/android/rendering_context_driver_vulkan_android.cpp index 9232126b0475..bc900350423e 100644 --- a/platform/android/rendering_context_driver_vulkan_android.cpp +++ b/platform/android/rendering_context_driver_vulkan_android.cpp @@ -29,6 +29,8 @@ /**************************************************************************/ #include "rendering_context_driver_vulkan_android.h" +#include "drivers/vulkan/rendering_native_surface_vulkan.h" +#include "rendering_native_surface_android.h" #ifdef VULKAN_ENABLED @@ -42,8 +44,9 @@ const char *RenderingContextDriverVulkanAndroid::_get_platform_surface_extension return VK_KHR_ANDROID_SURFACE_EXTENSION_NAME; } -RenderingContextDriver::SurfaceID RenderingContextDriverVulkanAndroid::surface_create(const void *p_platform_data) { - const WindowPlatformData *wpd = (const WindowPlatformData *)(p_platform_data); +RenderingContextDriver::SurfaceID RenderingContextDriverVulkanAndroid::surface_create(Ref p_native_surface) { + Ref android_native_surface = Object::cast_to(*p_native_surface); + ERR_FAIL_COND_V(android_native_surface.is_null(), SurfaceID()); VkAndroidSurfaceCreateInfoKHR create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; @@ -53,9 +56,10 @@ RenderingContextDriver::SurfaceID RenderingContextDriverVulkanAndroid::surface_c VkResult err = vkCreateAndroidSurfaceKHR(instance_get(), &create_info, nullptr, &vk_surface); ERR_FAIL_COND_V(err != VK_SUCCESS, SurfaceID()); - Surface *surface = memnew(Surface); - surface->vk_surface = vk_surface; - return SurfaceID(surface); + Ref vulkan_surface = RenderingNativeSurfaceVulkan::create(vk_surface); + RenderingContextDriver::SurfaceID result = RenderingContextDriverVulkan::surface_create(vulkan_surface); + memdelete(vulkan_surface); + return result; } bool RenderingContextDriverVulkanAndroid::_use_validation_layers() const { diff --git a/platform/android/rendering_context_driver_vulkan_android.h b/platform/android/rendering_context_driver_vulkan_android.h index a2a42eef2499..b646569eeac9 100644 --- a/platform/android/rendering_context_driver_vulkan_android.h +++ b/platform/android/rendering_context_driver_vulkan_android.h @@ -42,14 +42,10 @@ class RenderingContextDriverVulkanAndroid : public RenderingContextDriverVulkan virtual const char *_get_platform_surface_extension() const override final; protected: - SurfaceID surface_create(const void *p_platform_data) override final; + SurfaceID surface_create(Ref p_native_surface) override final; bool _use_validation_layers() const override final; public: - struct WindowPlatformData { - ANativeWindow *window; - }; - RenderingContextDriverVulkanAndroid() = default; ~RenderingContextDriverVulkanAndroid() override = default; }; diff --git a/platform/android/rendering_native_surface_android.cpp b/platform/android/rendering_native_surface_android.cpp new file mode 100644 index 000000000000..47cecaa7ddeb --- /dev/null +++ b/platform/android/rendering_native_surface_android.cpp @@ -0,0 +1,65 @@ +/**************************************************************************/ +/* rendering_native_surface_android.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "rendering_native_surface_android.h" + +#if defined(VULKAN_ENABLED) +#include "rendering_context_driver_vulkan_android.h" +#endif + +void RenderingNativeSurfaceAndroid::_bind_methods() { + ClassDB::bind_static_method("RenderingNativeSurfaceAndroid", D_METHOD("create", "window"), &RenderingNativeSurfaceAndroid::create_api); +} + +Ref RenderingNativeSurfaceAndroid::create_api(GDExtensionConstPtr p_window) { + return RenderingNativeSurfaceAndroid::create((ANativeWindow *)p_window.operator const void *()); +} + +Ref RenderingNativeSurfaceAndroid::create(ANativeWindow *p_window) { + Ref result = memnew(RenderingNativeSurfaceAndroid); + result->window = p_window; + return result; +} + +RenderingContextDriver *RenderingNativeSurfaceAndroid::create_rendering_context() { +#if defined(VULKAN_ENABLED) + return memnew(RenderingContextDriverVulkanAndroid); +#else + return nullptr; +#endif +} + +RenderingNativeSurfaceAndroid::RenderingNativeSurfaceAndroid() { + // Does nothing. +} + +RenderingNativeSurfaceAndroid::~RenderingNativeSurfaceAndroid() { + // Does nothing. +} diff --git a/platform/android/rendering_native_surface_android.h b/platform/android/rendering_native_surface_android.h new file mode 100644 index 000000000000..f1b5ac28ef26 --- /dev/null +++ b/platform/android/rendering_native_surface_android.h @@ -0,0 +1,61 @@ +/**************************************************************************/ +/* rendering_native_surface_android.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef RENDERING_NATIVE_SURFACE_ANDROID_H +#define RENDERING_NATIVE_SURFACE_ANDROID_H + +#include "core/variant/native_ptr.h" +#include "servers/rendering/rendering_native_surface.h" + +struct ANativeWindow; + +class RenderingNativeSurfaceAndroid : public RenderingNativeSurface { + GDCLASS(RenderingNativeSurfaceAndroid, RenderingNativeSurface); + + static void _bind_methods(); + + ANativeWindow *window; + +public: + static Ref create_api(GDExtensionConstPtr p_window); + + static Ref create(ANativeWindow *p_window); + + ANativeWindow *get_window() const { + return window; + }; + + RenderingContextDriver *create_rendering_context() override; + + RenderingNativeSurfaceAndroid(); + ~RenderingNativeSurfaceAndroid(); +}; + +#endif // RENDERING_NATIVE_SURFACE_ANDROID_H diff --git a/platform/ios/SCsub b/platform/ios/SCsub index cff7dcc1fd10..a7088feb4049 100644 --- a/platform/ios/SCsub +++ b/platform/ios/SCsub @@ -58,29 +58,39 @@ def generate_bundle(target, source, env): shutil.rmtree(app_dir) -ios_lib = [ - "godot_ios.mm", +common_ios_lib_files = [ "os_ios.mm", - "main.m", - "app_delegate.mm", - "view_controller.mm", "ios.mm", - "rendering_context_driver_vulkan_ios.mm", - "display_server_ios.mm", "joypad_ios.mm", + "ios_terminal_logger.mm", +] + +ios_lib_files = [ + "display_server_ios.mm", + "display_layer.mm", + "device_metrics.m", + "app_delegate.mm", + "view_controller.mm", "godot_view.mm", "tts_ios.mm", - "display_layer.mm", "godot_app_delegate.m", "godot_view_renderer.mm", - "device_metrics.m", "keyboard_input_view.mm", "key_mapping_ios.mm", - "ios_terminal_logger.mm", + "godot_ios.mm", + "main.m", +] + +ios_libgodot_files = [ + "libgodot_ios.mm", ] env_ios = env.Clone() -ios_lib = env_ios.add_library("ios", ios_lib) + +if env["library_type"] != "executable": + ios_lib = env_ios.add_library("ios", common_ios_lib_files + ios_libgodot_files) +else: + ios_lib = env_ios.add_library("ios", common_ios_lib_files + ios_lib_files) # (iOS) Enable module support env_ios.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) @@ -93,7 +103,11 @@ def combine_libs(target=None, source=None, env=None): else: libtool = "$IOS_TOOLCHAIN_PATH/usr/bin/libtool" env.Execute( - libtool + ' -static -o "' + lib_path + '" ' + " ".join([('"' + lib.srcnode().abspath + '"') for lib in source]) + libtool + + ' -static -a -o "' + + lib_path + + '" ' + + " ".join([('"' + lib.srcnode().abspath + '"') for lib in source]) ) diff --git a/platform/ios/api/api.cpp b/platform/ios/api/api.cpp index b8c9e7e9aabe..c3abd1e41403 100644 --- a/platform/ios/api/api.cpp +++ b/platform/ios/api/api.cpp @@ -32,16 +32,28 @@ #if defined(IOS_ENABLED) +void register_core_ios_api() { +} + +void unregister_core_ios_api() { +} + void register_ios_api() { +#ifndef IOS_LIBGODOT_ENABLED godot_ios_plugins_initialize(); +#endif } void unregister_ios_api() { +#ifndef IOS_LIBGODOT_ENABLED godot_ios_plugins_deinitialize(); +#endif } #else +void register_core_ios_api() {} +void unregister_core_ios_api() {} void register_ios_api() {} void unregister_ios_api() {} diff --git a/platform/ios/api/api.h b/platform/ios/api/api.h index 15634722bf0e..a55d1956d67b 100644 --- a/platform/ios/api/api.h +++ b/platform/ios/api/api.h @@ -36,6 +36,8 @@ extern void godot_ios_plugins_initialize(); extern void godot_ios_plugins_deinitialize(); #endif +void register_core_ios_api(); +void unregister_core_ios_api(); void register_ios_api(); void unregister_ios_api(); diff --git a/platform/ios/detect.py b/platform/ios/detect.py index 53b367a0a7f2..70a58a9b44ce 100644 --- a/platform/ios/detect.py +++ b/platform/ios/detect.py @@ -154,6 +154,9 @@ def configure(env: "SConsEnvironment"): env.Prepend(CPPPATH=["#platform/ios"]) env.Append(CPPDEFINES=["IOS_ENABLED", "UNIX_ENABLED", "COREAUDIO_ENABLED"]) + if env["library_type"] != "executable": + env.Append(CPPDEFINES=["IOS_LIBGODOT_ENABLED"]) + if env["vulkan"]: env.Append(CPPDEFINES=["VULKAN_ENABLED", "RD_ENABLED"]) diff --git a/platform/ios/display_server_ios.h b/platform/ios/display_server_ios.h index 4dded5aa2939..fa72ca849fa0 100644 --- a/platform/ios/display_server_ios.h +++ b/platform/ios/display_server_ios.h @@ -39,7 +39,6 @@ #include "servers/rendering/rendering_device.h" #if defined(VULKAN_ENABLED) -#import "rendering_context_driver_vulkan_ios.h" #ifdef USE_VOLK #include diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm index 802fbefc0dbb..503faae9619a 100644 --- a/platform/ios/display_server_ios.mm +++ b/platform/ios/display_server_ios.mm @@ -69,11 +69,7 @@ CALayer *layer = nullptr; - union { -#ifdef VULKAN_ENABLED - RenderingContextDriverVulkanIOS::WindowPlatformData vulkan; -#endif - } wpd; + Ref apple_surface; #if defined(VULKAN_ENABLED) if (rendering_driver == "vulkan") { @@ -81,8 +77,8 @@ if (!layer) { ERR_FAIL_MSG("Failed to create iOS Vulkan rendering layer."); } - wpd.vulkan.layer_ptr = (CAMetalLayer *const *)&layer; - rendering_context = memnew(RenderingContextDriverVulkanIOS); + apple_surface = RenderingNativeSurfaceApple::create((CAMetalLayer *const *)&layer); + rendering_context = apple_surface->create_rendering_context(); } #endif @@ -95,7 +91,7 @@ return; } - if (rendering_context->window_create(MAIN_WINDOW_ID, &wpd) != OK) { + if (rendering_context->window_create(MAIN_WINDOW_ID, apple_surface) != OK) { ERR_PRINT(vformat("Failed to create %s window.", rendering_driver)); memdelete(rendering_context); rendering_context = nullptr; diff --git a/platform/ios/ios.mm b/platform/ios/ios.mm index 6943de5ac889..632faa9b60d2 100644 --- a/platform/ios/ios.mm +++ b/platform/ios/ios.mm @@ -30,8 +30,10 @@ #import "ios.h" +#ifndef IOS_LIBGODOT_ENABLED #import "app_delegate.h" #import "view_controller.h" +#endif #import #import @@ -159,6 +161,7 @@ } void iOS::alert(const char *p_alert, const char *p_title) { +#ifndef IOS_LIBGODOT_ENABLED NSString *title = [NSString stringWithUTF8String:p_title]; NSString *message = [NSString stringWithUTF8String:p_alert]; @@ -171,6 +174,7 @@ [alert addAction:button]; [AppDelegate.viewController presentViewController:alert animated:YES completion:nil]; +#endif } String iOS::get_model() const { diff --git a/platform/ios/joypad_ios.mm b/platform/ios/joypad_ios.mm index 38d3ce728aaf..41340a85e35c 100644 --- a/platform/ios/joypad_ios.mm +++ b/platform/ios/joypad_ios.mm @@ -30,7 +30,6 @@ #import "joypad_ios.h" -#import "godot_view.h" #import "os_ios.h" #include "core/config/project_settings.h" diff --git a/platform/ios/libgodot_ios.mm b/platform/ios/libgodot_ios.mm new file mode 100644 index 000000000000..c1c780168f9d --- /dev/null +++ b/platform/ios/libgodot_ios.mm @@ -0,0 +1,69 @@ +/**************************************************************************/ +/* libgodot_ios.mm */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "core/extension/godot_instance.h" +#include "core/extension/libgodot.h" +#include "main/main.h" + +#import "os_ios.h" + +static OS_IOS *os = nullptr; + +static GodotInstance *instance = nullptr; + +GDExtensionObjectPtr libgodot_create_godot_instance(int p_argc, char *p_argv[], GDExtensionInitializationFunction p_init_func) { + ERR_FAIL_COND_V_MSG(instance != nullptr, nullptr, "Only one Godot Instance may be created."); + + os = new OS_IOS(); + + Error err = Main::setup(p_argv[0], p_argc - 1, &p_argv[1], false); + if (err != OK) { + return nullptr; + } + + instance = memnew(GodotInstance); + if (!instance->initialize(p_init_func)) { + memdelete(instance); + instance = nullptr; + return nullptr; + } + + return (GDExtensionObjectPtr)instance; +} + +void libgodot_destroy_godot_instance(GDExtensionObjectPtr p_godot_instance) { + GodotInstance *godot_instance = (GodotInstance *)p_godot_instance; + if (instance == godot_instance) { + godot_instance->stop(); + memdelete(godot_instance); + instance = nullptr; + Main::cleanup(); + } +} diff --git a/platform/ios/os_ios.h b/platform/ios/os_ios.h index b7c5a7306560..85595bdb8333 100644 --- a/platform/ios/os_ios.h +++ b/platform/ios/os_ios.h @@ -45,7 +45,7 @@ #include "servers/rendering/rendering_device.h" #if defined(VULKAN_ENABLED) -#import "rendering_context_driver_vulkan_ios.h" +#include "drivers/vulkan/rendering_context_driver_vulkan_moltenvk.h" #endif #endif diff --git a/platform/ios/os_ios.mm b/platform/ios/os_ios.mm index 35b87ea64703..d2f648977751 100644 --- a/platform/ios/os_ios.mm +++ b/platform/ios/os_ios.mm @@ -32,11 +32,14 @@ #ifdef IOS_ENABLED +#import "ios_terminal_logger.h" + +#ifndef IOS_LIBGODOT_ENABLED #import "app_delegate.h" #import "display_server_ios.h" #import "godot_view.h" -#import "ios_terminal_logger.h" #import "view_controller.h" +#endif #include "core/config/project_settings.h" #include "core/io/dir_access.h" @@ -44,6 +47,7 @@ #include "core/io/file_access_pack.h" #include "drivers/unix/syslog_logger.h" #include "main/main.h" +#include "servers/display_server_embedded.h" #import #import @@ -111,7 +115,10 @@ void register_dynamic_symbol(char *name, void *address) { AudioDriverManager::add_driver(&audio_driver); +#ifndef IOS_LIBGODOT_ENABLED DisplayServerIOS::register_ios_driver(); +#endif + DisplayServerEmbedded::register_embedded_driver(); } OS_IOS::~OS_IOS() {} @@ -599,15 +606,19 @@ void register_dynamic_symbol(char *name, void *address) { if (is_focused) { is_focused = false; +#ifndef IOS_LIBGODOT_ENABLED if (DisplayServerIOS::get_singleton()) { DisplayServerIOS::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_OUT); } +#endif if (OS::get_singleton()->get_main_loop()) { OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT); } +#ifndef IOS_LIBGODOT_ENABLED [AppDelegate.viewController.godotView stopRendering]; +#endif audio_driver.stop(); } @@ -617,15 +628,19 @@ void register_dynamic_symbol(char *name, void *address) { if (!is_focused) { is_focused = true; +#ifndef IOS_LIBGODOT_ENABLED if (DisplayServerIOS::get_singleton()) { DisplayServerIOS::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_IN); } +#endif if (OS::get_singleton()->get_main_loop()) { OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN); } +#ifndef IOS_LIBGODOT_ENABLED [AppDelegate.viewController.godotView startRendering]; +#endif audio_driver.start(); } diff --git a/platform/linuxbsd/SCsub b/platform/linuxbsd/SCsub index 0802b528f4b0..8aa16e7322bb 100644 --- a/platform/linuxbsd/SCsub +++ b/platform/linuxbsd/SCsub @@ -12,6 +12,12 @@ common_linuxbsd = [ "freedesktop_screensaver.cpp", ] +libgodot_files = [ + "libgodot_linuxbsd.cpp", +] + +executable_files = ["godot_linuxbsd.cpp"] + if env["use_sowrap"]: common_linuxbsd.append("xkbcommon-so_wrap.c") @@ -38,7 +44,12 @@ if env["dbus"]: if env["use_sowrap"]: common_linuxbsd.append("dbus-so_wrap.c") -prog = env.add_program("#bin/godot", ["godot_linuxbsd.cpp"] + common_linuxbsd) +if env["library_type"] == "static_library": + prog = env.add_library("#bin/godot", common_linuxbsd + libgodot_files) +elif env["library_type"] == "shared_library": + prog = env.add_shared_library("#bin/godot", common_linuxbsd + libgodot_files) +else: + prog = env.add_program("#bin/godot", common_linuxbsd + executable_files) if env["debug_symbols"] and env["separate_debug_symbols"]: env.AddPostAction(prog, env.Run(platform_linuxbsd_builders.make_debug_linuxbsd)) diff --git a/platform/linuxbsd/api/api.cpp b/platform/linuxbsd/api/api.cpp new file mode 100644 index 000000000000..ae3c42098c18 --- /dev/null +++ b/platform/linuxbsd/api/api.cpp @@ -0,0 +1,64 @@ +/**************************************************************************/ +/* api.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "api.h" + +#ifdef LINUXBSD_ENABLED +#include "core/object/class_db.h" + +#ifdef WAYLAND_ENABLED +#include "platform/linuxbsd/wayland/rendering_native_surface_wayland.h" +#endif + +#ifdef X11_ENABLED +#include "platform/linuxbsd/x11/rendering_native_surface_x11.h" +#endif + +#endif + +void register_core_linuxbsd_api() { +#ifdef LINUXBSD_ENABLED +#ifdef WAYLAND_ENABLED + GDREGISTER_ABSTRACT_CLASS(RenderingNativeSurfaceWayland); +#endif +#ifdef X11_ENABLED + GDREGISTER_ABSTRACT_CLASS(RenderingNativeSurfaceX11); +#endif +#endif +} + +void unregister_core_linuxbsd_api() { +} + +void register_linuxbsd_api() { +} + +void unregister_linuxbsd_api() { +} diff --git a/platform/linuxbsd/api/api.h b/platform/linuxbsd/api/api.h new file mode 100644 index 000000000000..273cbaea8289 --- /dev/null +++ b/platform/linuxbsd/api/api.h @@ -0,0 +1,39 @@ +/**************************************************************************/ +/* api.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef LINUXBSD_API_H +#define LINUXBSD_API_H + +void register_core_linuxbsd_api(); +void unregister_core_linuxbsd_api(); +void register_linuxbsd_api(); +void unregister_linuxbsd_api(); + +#endif // LINUXBSD_API_H diff --git a/platform/linuxbsd/libgodot_linuxbsd.cpp b/platform/linuxbsd/libgodot_linuxbsd.cpp new file mode 100644 index 000000000000..01f8ea7f456c --- /dev/null +++ b/platform/linuxbsd/libgodot_linuxbsd.cpp @@ -0,0 +1,70 @@ +/**************************************************************************/ +/* libgodot_linuxbsd.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "core/extension/libgodot.h" + +#include "core/extension/godot_instance.h" +#include "main/main.h" + +#include "os_linuxbsd.h" + +static OS_LinuxBSD *os = nullptr; + +static GodotInstance *instance = nullptr; + +GDExtensionObjectPtr libgodot_create_godot_instance(int p_argc, char *p_argv[], GDExtensionInitializationFunction p_init_func) { + ERR_FAIL_COND_V_MSG(instance != nullptr, nullptr, "Only one Godot Instance may be created."); + + os = new OS_LinuxBSD(); + + Error err = Main::setup(p_argv[0], p_argc - 1, &p_argv[1], false); + if (err != OK) { + return nullptr; + } + + instance = memnew(GodotInstance); + if (!instance->initialize(p_init_func)) { + memdelete(instance); + instance = nullptr; + return nullptr; + } + + return (GDExtensionObjectPtr)instance; +} + +void libgodot_destroy_godot_instance(GDExtensionObjectPtr p_godot_instance) { + GodotInstance *godot_instance = (GodotInstance *)p_godot_instance; + if (instance == godot_instance) { + godot_instance->stop(); + memdelete(godot_instance); + instance = nullptr; + Main::cleanup(); + } +} diff --git a/platform/linuxbsd/wayland/SCsub b/platform/linuxbsd/wayland/SCsub index 89b586845cea..d6b960ad93cb 100644 --- a/platform/linuxbsd/wayland/SCsub +++ b/platform/linuxbsd/wayland/SCsub @@ -190,6 +190,7 @@ source_files = [ "wayland_thread.cpp", "key_mapping_xkb.cpp", "detect_prime_egl.cpp", + "rendering_native_surface_wayland.cpp", ] if env["use_sowrap"]: diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp index adc9beed66ea..9cea76a0fec5 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.cpp +++ b/platform/linuxbsd/wayland/display_server_wayland.cpp @@ -50,6 +50,8 @@ #include "wayland/egl_manager_wayland_gles.h" #endif +#include "rendering_native_surface_wayland.h" + String DisplayServerWayland::_get_app_id_from_context(Context p_context) { String app_id; @@ -118,7 +120,7 @@ void DisplayServerWayland::_resize_window(const Size2i &p_size) { } } -void DisplayServerWayland::_show_window() { +bool DisplayServerWayland::_show_window() { MutexLock mutex_lock(wayland_thread.mutex); WindowData &wd = main_window; @@ -142,30 +144,41 @@ void DisplayServerWayland::_show_window() { // the only acceptable way of implementing window showing is to move the // graphics context window creation logic here. #ifdef RD_ENABLED - if (rendering_context) { - union { + Ref wayland_surface; #ifdef VULKAN_ENABLED - RenderingContextDriverVulkanWayland::WindowPlatformData vulkan; + if (rendering_driver == "vulkan") { + wayland_surface = RenderingNativeSurfaceWayland::create( + wayland_thread.get_wl_display(), + wayland_thread.window_get_wl_surface(wd.id)); + } #endif - } wpd; + #ifdef VULKAN_ENABLED - if (rendering_driver == "vulkan") { - wpd.vulkan.surface = wayland_thread.window_get_wl_surface(wd.id); - wpd.vulkan.display = wayland_thread.get_wl_display(); - } + if (wayland_surface.is_valid()) { + rendering_context = wayland_surface->create_rendering_context(); + } #endif - Error err = rendering_context->window_create(wd.id, &wpd); - ERR_FAIL_COND_MSG(err != OK, vformat("Can't create a %s window", rendering_driver)); - rendering_context->window_set_size(wd.id, wd.rect.size.width, wd.rect.size.height); - rendering_context->window_set_vsync_mode(wd.id, wd.vsync_mode); + if (rendering_context) { + if (rendering_context->initialize() != OK) { + ERR_PRINT(vformat("Could not initialize %s", rendering_driver)); + memdelete(rendering_context); + rendering_context = nullptr; + return false; + } + } - emulate_vsync = (rendering_context->window_get_vsync_mode(wd.id) == DisplayServer::VSYNC_ENABLED); + Error err = rendering_context->window_create(wd.id, wayland_surface); + ERR_FAIL_COND_V_MSG(err != OK, false, vformat("Can't create a %s window", rendering_driver)); - if (emulate_vsync) { - print_verbose("VSYNC: manually throttling frames using MAILBOX."); - rendering_context->window_set_vsync_mode(wd.id, DisplayServer::VSYNC_MAILBOX); - } + rendering_context->window_set_size(wd.id, wd.rect.size.width, wd.rect.size.height); + rendering_context->window_set_vsync_mode(wd.id, wd.vsync_mode); + + emulate_vsync = (rendering_context->window_get_vsync_mode(wd.id) == DisplayServer::VSYNC_ENABLED); + + if (emulate_vsync) { + print_verbose("VSYNC: manually throttling frames using MAILBOX."); + rendering_context->window_set_vsync_mode(wd.id, DisplayServer::VSYNC_MAILBOX); } #endif @@ -175,7 +188,7 @@ void DisplayServerWayland::_show_window() { wd.wl_egl_window = wl_egl_window_create(wl_surface, wd.rect.size.width, wd.rect.size.height); Error err = egl_manager->window_create(MAIN_WINDOW_ID, wayland_thread.get_wl_display(), wd.wl_egl_window, wd.rect.size.width, wd.rect.size.height); - ERR_FAIL_COND_MSG(err == ERR_CANT_CREATE, "Can't show a GLES3 window."); + ERR_FAIL_COND_V_MSG(err == ERR_CANT_CREATE, false, "Can't show a GLES3 window."); window_set_vsync_mode(wd.vsync_mode, MAIN_WINDOW_ID); } @@ -189,6 +202,8 @@ void DisplayServerWayland::_show_window() { wayland_thread.window_set_title(MAIN_WINDOW_ID, wd.title); } + + return true; } // Interface methods. @@ -1349,24 +1364,6 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win rendering_driver = p_rendering_driver; -#ifdef RD_ENABLED -#ifdef VULKAN_ENABLED - if (rendering_driver == "vulkan") { - rendering_context = memnew(RenderingContextDriverVulkanWayland); - } -#endif - - 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; - } - } -#endif - #ifdef GLES3_ENABLED if (rendering_driver == "opengl3" || rendering_driver == "opengl3_es") { #ifdef SOWRAP_ENABLED @@ -1464,7 +1461,10 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win wd.rect.size = p_resolution; wd.title = "Godot"; - _show_window(); + if (!_show_window()) { + r_error = ERR_CANT_CREATE; + ERR_FAIL_MSG("Could not initialize window."); + } #ifdef RD_ENABLED if (rendering_context) { diff --git a/platform/linuxbsd/wayland/display_server_wayland.h b/platform/linuxbsd/wayland/display_server_wayland.h index e61153366421..d51c4d2062fe 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.h +++ b/platform/linuxbsd/wayland/display_server_wayland.h @@ -152,7 +152,7 @@ class DisplayServerWayland : public DisplayServer { void _resize_window(const Size2i &p_size); - virtual void _show_window(); + bool _show_window(); void try_suspend(); diff --git a/platform/linuxbsd/wayland/rendering_context_driver_vulkan_wayland.cpp b/platform/linuxbsd/wayland/rendering_context_driver_vulkan_wayland.cpp index c874c45a8a65..226804ac7f5d 100644 --- a/platform/linuxbsd/wayland/rendering_context_driver_vulkan_wayland.cpp +++ b/platform/linuxbsd/wayland/rendering_context_driver_vulkan_wayland.cpp @@ -31,6 +31,8 @@ #ifdef VULKAN_ENABLED #include "rendering_context_driver_vulkan_wayland.h" +#include "drivers/vulkan/rendering_native_surface_vulkan.h" +#include "rendering_native_surface_wayland.h" #ifdef USE_VOLK #include @@ -42,21 +44,22 @@ const char *RenderingContextDriverVulkanWayland::_get_platform_surface_extension return VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME; } -RenderingContextDriver::SurfaceID RenderingContextDriverVulkanWayland::surface_create(const void *p_platform_data) { - const WindowPlatformData *wpd = (const WindowPlatformData *)(p_platform_data); +RenderingContextDriver::SurfaceID RenderingContextDriverVulkanWayland::surface_create(Ref p_native_surface) { + Ref wayland_native_surface = Object::cast_to(*p_native_surface); + ERR_FAIL_COND_V(wayland_native_surface.is_null(), SurfaceID()); VkWaylandSurfaceCreateInfoKHR create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR; - create_info.display = wpd->display; - create_info.surface = wpd->surface; + create_info.display = wayland_native_surface->get_display(); + create_info.surface = wayland_native_surface->get_surface(); VkSurfaceKHR vk_surface = VK_NULL_HANDLE; VkResult err = vkCreateWaylandSurfaceKHR(instance_get(), &create_info, nullptr, &vk_surface); ERR_FAIL_COND_V(err != VK_SUCCESS, SurfaceID()); - Surface *surface = memnew(Surface); - surface->vk_surface = vk_surface; - return SurfaceID(surface); + Ref vulkan_surface = RenderingNativeSurfaceVulkan::create(vk_surface); + RenderingContextDriver::SurfaceID result = RenderingContextDriverVulkan::surface_create(vulkan_surface); + return result; } RenderingContextDriverVulkanWayland::RenderingContextDriverVulkanWayland() { diff --git a/platform/linuxbsd/wayland/rendering_context_driver_vulkan_wayland.h b/platform/linuxbsd/wayland/rendering_context_driver_vulkan_wayland.h index dfebca189034..5f49c5db4725 100644 --- a/platform/linuxbsd/wayland/rendering_context_driver_vulkan_wayland.h +++ b/platform/linuxbsd/wayland/rendering_context_driver_vulkan_wayland.h @@ -40,14 +40,9 @@ class RenderingContextDriverVulkanWayland : public RenderingContextDriverVulkan virtual const char *_get_platform_surface_extension() const override final; protected: - SurfaceID surface_create(const void *p_platform_data) override final; + SurfaceID surface_create(Ref p_native_surface) override final; public: - struct WindowPlatformData { - struct wl_display *display; - struct wl_surface *surface; - }; - RenderingContextDriverVulkanWayland(); ~RenderingContextDriverVulkanWayland(); }; diff --git a/platform/linuxbsd/wayland/rendering_native_surface_wayland.cpp b/platform/linuxbsd/wayland/rendering_native_surface_wayland.cpp new file mode 100644 index 000000000000..df182d526365 --- /dev/null +++ b/platform/linuxbsd/wayland/rendering_native_surface_wayland.cpp @@ -0,0 +1,67 @@ +/**************************************************************************/ +/* rendering_native_surface_wayland.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "rendering_native_surface_wayland.h" +#include "core/object/class_db.h" + +#ifdef VULKAN_ENABLED +#include "wayland/rendering_context_driver_vulkan_wayland.h" +#endif + +void RenderingNativeSurfaceWayland::_bind_methods() { + ClassDB::bind_static_method("RenderingNativeSurfaceWayland", D_METHOD("create", "window", "display"), &RenderingNativeSurfaceWayland::create_api); +} + +Ref RenderingNativeSurfaceWayland::create_api(GDExtensionConstPtr p_display, GDExtensionConstPtr p_surface) { + return RenderingNativeSurfaceWayland::create((struct wl_display *)p_display.operator const void *(), (struct wl_surface *)p_surface.operator const void *()); +} + +Ref RenderingNativeSurfaceWayland::create(struct wl_display *p_display, struct wl_surface *p_surface) { + Ref result = memnew(RenderingNativeSurfaceWayland); + result->surface = p_surface; + result->display = p_display; + return result; +} + +RenderingContextDriver *RenderingNativeSurfaceWayland::create_rendering_context() { +#if defined(VULKAN_ENABLED) + return memnew(RenderingContextDriverVulkanWayland); +#else + return nullptr; +#endif +} + +RenderingNativeSurfaceWayland::RenderingNativeSurfaceWayland() { + // Does nothing. +} + +RenderingNativeSurfaceWayland::~RenderingNativeSurfaceWayland() { + // Does nothing. +} diff --git a/platform/linuxbsd/wayland/rendering_native_surface_wayland.h b/platform/linuxbsd/wayland/rendering_native_surface_wayland.h new file mode 100644 index 000000000000..69af18420ad3 --- /dev/null +++ b/platform/linuxbsd/wayland/rendering_native_surface_wayland.h @@ -0,0 +1,64 @@ +/**************************************************************************/ +/* rendering_native_surface_wayland.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef RENDERING_NATIVE_SURFACE_WAYLAND_H +#define RENDERING_NATIVE_SURFACE_WAYLAND_H + +#include "core/variant/native_ptr.h" +#include "servers/rendering/rendering_native_surface.h" + +class RenderingNativeSurfaceWayland : public RenderingNativeSurface { + GDCLASS(RenderingNativeSurfaceWayland, RenderingNativeSurface); + + static void _bind_methods(); + + struct wl_display *display; + struct wl_surface *surface; + +public: + static Ref create_api(GDExtensionConstPtr p_display, GDExtensionConstPtr p_surface); + + static Ref create(struct wl_display *p_display, wl_surface *p_surface); + + struct wl_display *get_display() const { + return display; + }; + + struct wl_surface *get_surface() const { + return surface; + }; + + RenderingContextDriver *create_rendering_context() override; + + RenderingNativeSurfaceWayland(); + ~RenderingNativeSurfaceWayland(); +}; + +#endif // RENDERING_NATIVE_SURFACE_WAYLAND_H diff --git a/platform/linuxbsd/x11/SCsub b/platform/linuxbsd/x11/SCsub index 75fe584ad58c..689f6fa7b851 100644 --- a/platform/linuxbsd/x11/SCsub +++ b/platform/linuxbsd/x11/SCsub @@ -5,6 +5,7 @@ Import("env") source_files = [ "display_server_x11.cpp", "key_mapping_x11.cpp", + "rendering_native_surface_x11.cpp", ] if env["use_sowrap"]: diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index edf3a40ccb4e..9a16e904ce91 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -42,6 +42,8 @@ #include "drivers/png/png_driver_common.h" #include "main/main.h" +#include "rendering_native_surface_x11.h" + #if defined(VULKAN_ENABLED) #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #endif @@ -5717,19 +5719,29 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V _update_size_hints(id); #if defined(RD_ENABLED) - if (rendering_context) { - union { + Ref x11_surface = nullptr; #ifdef VULKAN_ENABLED - RenderingContextDriverVulkanX11::WindowPlatformData vulkan; + if (rendering_driver == "vulkan") { + x11_surface = RenderingNativeSurfaceX11::create(wd.x11_window, x11_display); + } #endif - } wpd; -#ifdef VULKAN_ENABLED - if (rendering_driver == "vulkan") { - wpd.vulkan.window = wd.x11_window; - wpd.vulkan.display = x11_display; + + if (!rendering_context) { + if (x11_surface.is_valid()) { + rendering_context = x11_surface->create_rendering_context(); } -#endif - Error err = rendering_context->window_create(id, &wpd); + + if (rendering_context) { + if (rendering_context->initialize() != OK) { + memdelete(rendering_context); + rendering_context = nullptr; + ERR_FAIL_V_MSG(INVALID_WINDOW_ID, vformat("Could not initialize %s", rendering_driver)); + } + } + } + + if (rendering_context) { + Error err = rendering_context->window_create(id, x11_surface); ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, vformat("Can't create a %s window", rendering_driver)); rendering_context->window_set_size(id, win_rect.size.width, win_rect.size.height); @@ -6138,22 +6150,11 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode bool driver_found = false; #if defined(RD_ENABLED) -#if defined(VULKAN_ENABLED) +#ifdef VULKAN_ENABLED if (rendering_driver == "vulkan") { - rendering_context = memnew(RenderingContextDriverVulkanX11); - } -#endif - - 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; - } driver_found = true; } +#endif #endif // Initialize context and rendering device. #if defined(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 bf44062266d9..2d91812f73de 100644 --- a/platform/linuxbsd/x11/rendering_context_driver_vulkan_x11.cpp +++ b/platform/linuxbsd/x11/rendering_context_driver_vulkan_x11.cpp @@ -31,6 +31,8 @@ #ifdef VULKAN_ENABLED #include "rendering_context_driver_vulkan_x11.h" +#include "drivers/vulkan/rendering_native_surface_vulkan.h" +#include "rendering_native_surface_x11.h" #ifdef USE_VOLK #include @@ -42,21 +44,22 @@ const char *RenderingContextDriverVulkanX11::_get_platform_surface_extension() c return VK_KHR_XLIB_SURFACE_EXTENSION_NAME; } -RenderingContextDriver::SurfaceID RenderingContextDriverVulkanX11::surface_create(const void *p_platform_data) { - const WindowPlatformData *wpd = (const WindowPlatformData *)(p_platform_data); +RenderingContextDriver::SurfaceID RenderingContextDriverVulkanX11::surface_create(Ref p_native_surface) { + Ref x11_native_surface = Object::cast_to(*p_native_surface); + ERR_FAIL_COND_V(x11_native_surface.is_null(), SurfaceID()); VkXlibSurfaceCreateInfoKHR create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; - create_info.dpy = wpd->display; - create_info.window = wpd->window; + create_info.dpy = x11_native_surface->get_display(); + create_info.window = x11_native_surface->get_window(); VkSurfaceKHR vk_surface = VK_NULL_HANDLE; VkResult err = vkCreateXlibSurfaceKHR(instance_get(), &create_info, nullptr, &vk_surface); ERR_FAIL_COND_V(err != VK_SUCCESS, SurfaceID()); - Surface *surface = memnew(Surface); - surface->vk_surface = vk_surface; - return SurfaceID(surface); + Ref vulkan_surface = RenderingNativeSurfaceVulkan::create(vk_surface); + RenderingContextDriver::SurfaceID result = RenderingContextDriverVulkan::surface_create(vulkan_surface); + return result; } RenderingContextDriverVulkanX11::RenderingContextDriverVulkanX11() { diff --git a/platform/linuxbsd/x11/rendering_context_driver_vulkan_x11.h b/platform/linuxbsd/x11/rendering_context_driver_vulkan_x11.h index d525b69ec7b0..59df31b4b99a 100644 --- a/platform/linuxbsd/x11/rendering_context_driver_vulkan_x11.h +++ b/platform/linuxbsd/x11/rendering_context_driver_vulkan_x11.h @@ -35,21 +35,14 @@ #include "drivers/vulkan/rendering_context_driver_vulkan.h" -#include - class RenderingContextDriverVulkanX11 : public RenderingContextDriverVulkan { private: virtual const char *_get_platform_surface_extension() const override final; protected: - SurfaceID surface_create(const void *p_platform_data) override final; + SurfaceID surface_create(Ref p_native_surface) override final; public: - struct WindowPlatformData { - ::Window window; - Display *display; - }; - RenderingContextDriverVulkanX11(); ~RenderingContextDriverVulkanX11(); }; diff --git a/platform/linuxbsd/x11/rendering_native_surface_x11.cpp b/platform/linuxbsd/x11/rendering_native_surface_x11.cpp new file mode 100644 index 000000000000..dcff03c01b85 --- /dev/null +++ b/platform/linuxbsd/x11/rendering_native_surface_x11.cpp @@ -0,0 +1,67 @@ +/**************************************************************************/ +/* rendering_native_surface_x11.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "rendering_native_surface_x11.h" +#include "core/object/class_db.h" + +#if defined(VULKAN_ENABLED) +#include "x11/rendering_context_driver_vulkan_x11.h" +#endif + +void RenderingNativeSurfaceX11::_bind_methods() { + ClassDB::bind_static_method("RenderingNativeSurfaceX11", D_METHOD("create", "window", "display"), &RenderingNativeSurfaceX11::create_api); +} + +Ref RenderingNativeSurfaceX11::create_api(GDExtensionConstPtr p_window, GDExtensionConstPtr p_display) { + return RenderingNativeSurfaceX11::create((::Window)p_window.operator const void *(), (Display *)p_display.operator const void *()); +} + +Ref RenderingNativeSurfaceX11::create(::Window p_window, Display *p_display) { + Ref result = memnew(RenderingNativeSurfaceX11); + result->window = p_window; + result->display = p_display; + return result; +} + +RenderingContextDriver *RenderingNativeSurfaceX11::create_rendering_context() { +#if defined(VULKAN_ENABLED) + return memnew(RenderingContextDriverVulkanX11); +#else + return nullptr; +#endif +} + +RenderingNativeSurfaceX11::RenderingNativeSurfaceX11() { + // Does nothing. +} + +RenderingNativeSurfaceX11::~RenderingNativeSurfaceX11() { + // Does nothing. +} diff --git a/platform/linuxbsd/x11/rendering_native_surface_x11.h b/platform/linuxbsd/x11/rendering_native_surface_x11.h new file mode 100644 index 000000000000..0e80ab42b7cd --- /dev/null +++ b/platform/linuxbsd/x11/rendering_native_surface_x11.h @@ -0,0 +1,66 @@ +/**************************************************************************/ +/* rendering_native_surface_x11.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef RENDERING_NATIVE_SURFACE_X11_H +#define RENDERING_NATIVE_SURFACE_X11_H + +#include "core/variant/native_ptr.h" +#include "servers/rendering/rendering_native_surface.h" + +#include + +class RenderingNativeSurfaceX11 : public RenderingNativeSurface { + GDCLASS(RenderingNativeSurfaceX11, RenderingNativeSurface); + + static void _bind_methods(); + + ::Window window; + Display *display; + +public: + static Ref create_api(GDExtensionConstPtr p_window, GDExtensionConstPtr p_display); + + static Ref create(::Window p_window, Display *p_display); + + ::Window get_window() const { + return window; + }; + + Display *get_display() const { + return display; + }; + + RenderingContextDriver *create_rendering_context() override; + + RenderingNativeSurfaceX11(); + ~RenderingNativeSurfaceX11(); +}; + +#endif // RENDERING_NATIVE_SURFACE_X11_H diff --git a/platform/macos/SCsub b/platform/macos/SCsub index c965e875c18d..483f36c372ec 100644 --- a/platform/macos/SCsub +++ b/platform/macos/SCsub @@ -98,7 +98,7 @@ def generate_bundle(target, source, env): shutil.rmtree(app_dir) -files = [ +common_files = [ "os_macos.mm", "godot_application.mm", "godot_application_delegate.mm", @@ -111,7 +111,6 @@ files = [ "godot_window_delegate.mm", "godot_window.mm", "key_mapping_macos.mm", - "godot_main_macos.mm", "godot_menu_delegate.mm", "godot_menu_item.mm", "godot_open_save_delegate.mm", @@ -119,12 +118,24 @@ files = [ "dir_access_macos.mm", "tts_macos.mm", "joypad_macos.mm", - "rendering_context_driver_vulkan_macos.mm", "gl_manager_macos_angle.mm", "gl_manager_macos_legacy.mm", ] -prog = env.add_program("#bin/godot", files) +executable_files = [ + "godot_main_macos.mm", +] + +libgodot_files = [ + "libgodot_macos.mm", +] + +if env["library_type"] == "static_library": + prog = env.add_library("#bin/godot", common_files + libgodot_files) +elif env["library_type"] == "shared_library": + prog = env.add_shared_library("#bin/godot", common_files + libgodot_files) +else: + prog = env.add_program("#bin/godot", common_files + executable_files) if env["debug_symbols"] and env["separate_debug_symbols"]: env.AddPostAction(prog, env.Run(platform_macos_builders.make_debug_macos)) diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index b4741dc08f49..730546fdb501 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -45,7 +45,7 @@ #include "servers/rendering/rendering_device.h" #if defined(VULKAN_ENABLED) -#include "rendering_context_driver_vulkan_macos.h" +#include "drivers/vulkan/rendering_context_driver_vulkan_moltenvk.h" #endif // VULKAN_ENABLED #endif // RD_ENABLED diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index a1a91345ac4f..421c8887b017 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -58,6 +58,8 @@ #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #endif +#include "drivers/apple/rendering_native_surface_apple.h" + #import #import #import @@ -134,18 +136,30 @@ } #if defined(RD_ENABLED) - if (rendering_context) { - union { + Ref apple_surface; #ifdef VULKAN_ENABLED - RenderingContextDriverVulkanMacOS::WindowPlatformData vulkan; + if (rendering_driver == "vulkan") { + apple_surface = RenderingNativeSurfaceApple::create((__bridge void *)layer); + } #endif - } wpd; -#ifdef VULKAN_ENABLED - if (rendering_driver == "vulkan") { - wpd.vulkan.layer_ptr = (CAMetalLayer *const *)&layer; + + if (!rendering_context) { + if (apple_surface.is_valid()) { + rendering_context = apple_surface->create_rendering_context(); } -#endif - Error err = rendering_context->window_create(window_id_counter, &wpd); + + if (rendering_context) { + if (rendering_context->initialize() != OK) { + memdelete(rendering_context); + rendering_context = nullptr; + ERR_PRINT("Could not initialize " + rendering_driver); + return INVALID_WINDOW_ID; + } + } + } + + if (rendering_context) { + Error err = rendering_context->window_create(window_id_counter, apple_surface); ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, vformat("Can't create a %s context", rendering_driver)); rendering_context->window_set_size(window_id_counter, p_rect.size.width, p_rect.size.height); @@ -3627,22 +3641,6 @@ } } #endif -#if defined(RD_ENABLED) -#if defined(VULKAN_ENABLED) - if (rendering_driver == "vulkan") { - rendering_context = memnew(RenderingContextDriverVulkanMacOS); - } -#endif - - if (rendering_context) { - if (rendering_context->initialize() != OK) { - memdelete(rendering_context); - rendering_context = nullptr; - r_error = ERR_CANT_CREATE; - ERR_FAIL_MSG("Could not initialize " + rendering_driver); - } - } -#endif Point2i window_position; if (p_position != nullptr) { @@ -3656,7 +3654,10 @@ } WindowID main_window = _create_window(p_mode, p_vsync_mode, Rect2i(window_position, p_resolution)); - ERR_FAIL_COND(main_window == INVALID_WINDOW_ID); + if (main_window == INVALID_WINDOW_ID) { + r_error = ERR_CANT_CREATE; + ERR_FAIL_MSG("Could not create main window."); + } for (int i = 0; i < WINDOW_FLAG_MAX; i++) { if (p_flags & (1 << i)) { window_set_flag(WindowFlags(i), true, main_window); diff --git a/platform/macos/libgodot_macos.mm b/platform/macos/libgodot_macos.mm new file mode 100644 index 000000000000..415351216650 --- /dev/null +++ b/platform/macos/libgodot_macos.mm @@ -0,0 +1,72 @@ +/**************************************************************************/ +/* libgodot_macos.mm */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "core/extension/libgodot.h" + +#include "core/extension/godot_instance.h" +#include "main/main.h" + +#include "os_macos.h" + +static OS_MacOS *os = nullptr; + +static GodotInstance *instance = nullptr; + +GDExtensionObjectPtr libgodot_create_godot_instance(int p_argc, char *p_argv[], GDExtensionInitializationFunction p_init_func) { + ERR_FAIL_COND_V_MSG(instance != nullptr, nullptr, "Only one Godot Instance may be created."); + + os = new OS_MacOS(); + + @autoreleasepool { + Error err = Main::setup(p_argv[0], p_argc - 1, &p_argv[1], false); + if (err != OK) { + return nullptr; + } + + instance = memnew(GodotInstance); + if (!instance->initialize(p_init_func)) { + memdelete(instance); + instance = nullptr; + return nullptr; + } + + return (GDExtensionObjectPtr)instance; + } +} + +void libgodot_destroy_godot_instance(GDExtensionObjectPtr p_godot_instance) { + GodotInstance *godot_instance = (GodotInstance *)p_godot_instance; + if (instance == godot_instance) { + godot_instance->stop(); + memdelete(godot_instance); + instance = nullptr; + Main::cleanup(); + } +} diff --git a/platform/register_platform_apis.h b/platform/register_platform_apis.h index bce486881e9a..f3a2becd192b 100644 --- a/platform/register_platform_apis.h +++ b/platform/register_platform_apis.h @@ -31,7 +31,9 @@ #ifndef REGISTER_PLATFORM_APIS_H #define REGISTER_PLATFORM_APIS_H +void register_core_platform_apis(); void register_platform_apis(); +void unregister_core_platform_apis(); void unregister_platform_apis(); #endif // REGISTER_PLATFORM_APIS_H diff --git a/platform/web/api/api.cpp b/platform/web/api/api.cpp index a695091a0496..84a56ceebeb1 100644 --- a/platform/web/api/api.cpp +++ b/platform/web/api/api.cpp @@ -37,6 +37,12 @@ static JavaScriptBridge *javascript_bridge_singleton; +void register_core_web_api() { +} + +void unregister_core_web_api() { +} + void register_web_api() { WebToolsEditorPlugin::initialize(); GDREGISTER_ABSTRACT_CLASS(JavaScriptObject); diff --git a/platform/web/api/api.h b/platform/web/api/api.h index 234bc6b326cc..d2367541dd9b 100644 --- a/platform/web/api/api.h +++ b/platform/web/api/api.h @@ -31,6 +31,8 @@ #ifndef WEB_API_H #define WEB_API_H +void register_core_web_api(); +void unregister_core_web_api(); void register_web_api(); void unregister_web_api(); diff --git a/platform/windows/SCsub b/platform/windows/SCsub index f2fb8616ae6a..275dfd86c231 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -23,6 +23,7 @@ common_win = [ "gl_manager_windows_angle.cpp", "wgl_detect_version.cpp", "rendering_context_driver_vulkan_windows.cpp", + "rendering_native_surface_windows.cpp", ] if env.msvc: @@ -55,28 +56,37 @@ env.Depends(res_obj, "#core/version_generated.gen.h") env.add_source_files(sources, common_win) sources += res_obj -prog = env.add_program("#bin/godot", sources, PROGSUFFIX=env["PROGSUFFIX"]) -arrange_program_clean(prog) - -# Build console wrapper app. -if env["windows_subsystem"] == "gui": - env_wrap = env.Clone() - res_wrap_file = "godot_res_wrap.rc" - res_wrap_target = "godot_res_wrap" + env["OBJSUFFIX"] - res_wrap_obj = env_wrap.RES(res_wrap_target, res_wrap_file) - env_wrap.Depends(res_wrap_obj, "#core/version_generated.gen.h") - - if env.msvc: - env_wrap.Append(LINKFLAGS=["/SUBSYSTEM:CONSOLE"]) - env_wrap.Append(LINKFLAGS=["version.lib"]) - else: - env_wrap.Append(LINKFLAGS=["-Wl,--subsystem,console"]) - env_wrap.Append(LIBS=["version"]) - - prog_wrap = env_wrap.add_program("#bin/godot", common_win_wrap + res_wrap_obj, PROGSUFFIX=env["PROGSUFFIX_WRAP"]) - arrange_program_clean(prog_wrap) - env_wrap.Depends(prog_wrap, prog) - sources += common_win_wrap + res_wrap_obj +if env["library_type"] == "static_library": + prog = env.add_library("#bin/godot", sources, PROGSUFFIX=env["PROGSUFFIX"]) + arrange_program_clean(prog) +elif env["library_type"] == "shared_library": + prog = env.add_shared_library("#bin/godot", sources, PROGSUFFIX=env["PROGSUFFIX"]) + arrange_program_clean(prog) +else: + prog = env.add_program("#bin/godot", sources, PROGSUFFIX=env["PROGSUFFIX"]) + arrange_program_clean(prog) + + # Build console wrapper app. + if env["windows_subsystem"] == "gui": + env_wrap = env.Clone() + res_wrap_file = "godot_res_wrap.rc" + res_wrap_target = "godot_res_wrap" + env["OBJSUFFIX"] + res_wrap_obj = env_wrap.RES(res_wrap_target, res_wrap_file) + env_wrap.Depends(res_wrap_obj, "#core/version_generated.gen.h") + + if env.msvc: + env_wrap.Append(LINKFLAGS=["/SUBSYSTEM:CONSOLE"]) + env_wrap.Append(LINKFLAGS=["version.lib"]) + else: + env_wrap.Append(LINKFLAGS=["-Wl,--subsystem,console"]) + env_wrap.Append(LIBS=["version"]) + + prog_wrap = env_wrap.add_program( + "#bin/godot", common_win_wrap + res_wrap_obj, PROGSUFFIX=env["PROGSUFFIX_WRAP"] + ) + arrange_program_clean(prog_wrap) + env_wrap.Depends(prog_wrap, prog) + sources += common_win_wrap + res_wrap_obj # Microsoft Visual Studio Project Generation if env["vsproj"]: diff --git a/platform/windows/api/api.cpp b/platform/windows/api/api.cpp new file mode 100644 index 000000000000..3d7888d5e4cd --- /dev/null +++ b/platform/windows/api/api.cpp @@ -0,0 +1,51 @@ +/**************************************************************************/ +/* api.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "api.h" + +#ifdef WINDOWS_ENABLED +#include "core/object/class_db.h" +#include "platform/windows/rendering_native_surface_windows.h" +#endif + +void register_core_windows_api() { +#ifdef WINDOWS_ENABLED + GDREGISTER_ABSTRACT_CLASS(RenderingNativeSurfaceWindows); +#endif +} + +void unregister_core_windows_api() { +} + +void register_windows_api() { +} + +void unregister_windows_api() { +} diff --git a/platform/windows/api/api.h b/platform/windows/api/api.h new file mode 100644 index 000000000000..6e46cfdcd7cd --- /dev/null +++ b/platform/windows/api/api.h @@ -0,0 +1,39 @@ +/**************************************************************************/ +/* api.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef WINDOWS_API_H +#define WINDOWS_API_H + +void register_core_windows_api(); +void unregister_core_windows_api(); +void register_windows_api(); +void unregister_windows_api(); + +#endif // WINDOWS_API_H diff --git a/platform/windows/detect.py b/platform/windows/detect.py index fee306a25c34..832f5ee6586a 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -376,7 +376,7 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config): ## Build type # TODO: Re-evaluate the need for this / streamline with common config. - if env["target"] == "template_release": + if env["target"] == "template_release" and env["library_type"] == "executable": env.Append(LINKFLAGS=["/ENTRY:mainCRTStartup"]) if env["windows_subsystem"] == "gui": diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 8d26a705a995..e021f13e4651 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -5247,29 +5247,42 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, } #ifdef RD_ENABLED - if (rendering_context) { - union { -#ifdef VULKAN_ENABLED - RenderingContextDriverVulkanWindows::WindowPlatformData vulkan; + Ref windows_surface = nullptr; +#ifdef VULKAN_ENABLED || D3D12_ENABLED + if (rendering_driver == "vulkan" || rendering_driver == "d3d12") { + windows_surface = RenderingNativeSurfaceWindows::create(wd.hWnd, hInstance); + } #endif -#ifdef D3D12_ENABLED - RenderingContextDriverD3D12::WindowPlatformData d3d12; + + if (!rendering_context) { + if (windows_surface.is_valid()) { +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { + windows_surface->set_driver_type(RenderingNativeSurfaceWindows::DriverType::Vulkan); + } #endif - } wpd; -#ifdef VULKAN_ENABLED - if (rendering_driver == "vulkan") { - wpd.vulkan.window = wd.hWnd; - wpd.vulkan.instance = hInstance; - } +#if defined(D3D12_ENABLED) + if (rendering_driver == "d3d12") { + windows_surface->set_driver_type(RenderingNativeSurfaceWindows::DriverType::D3D12); + } #endif -#ifdef D3D12_ENABLED - if (rendering_driver == "d3d12") { - wpd.d3d12.window = wd.hWnd; + rendering_context = windows_surface->create_rendering_context(); } -#endif - if (rendering_context->window_create(id, &wpd) != OK) { + + if (rendering_context) { + if (rendering_context->initialize() != OK) { + memdelete(rendering_context); + rendering_context = nullptr; + return INVALID_WINDOW_ID; + } + } + } + + if (rendering_context) { + if (rendering_context->window_create(id, windows_surface) != OK) { ERR_PRINT(vformat("Failed to create %s window.", rendering_driver)); memdelete(rendering_context); + memdelete(windows_surface); rendering_context = nullptr; windows.erase(id); return INVALID_WINDOW_ID; @@ -5278,6 +5291,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, rendering_context->window_set_size(id, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top); rendering_context->window_set_vsync_mode(id, p_vsync_mode); wd.context_created = true; + memdelete(windows_surface); } #endif @@ -5736,27 +5750,6 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win _register_raw_input_devices(INVALID_WINDOW_ID); -#if defined(RD_ENABLED) -#if defined(VULKAN_ENABLED) - if (rendering_driver == "vulkan") { - rendering_context = memnew(RenderingContextDriverVulkanWindows); - } -#endif -#if defined(D3D12_ENABLED) - if (rendering_driver == "d3d12") { - rendering_context = memnew(RenderingContextDriverD3D12); - } -#endif - - if (rendering_context) { - if (rendering_context->initialize() != OK) { - memdelete(rendering_context); - rendering_context = nullptr; - r_error = ERR_UNAVAILABLE; - return; - } - } -#endif // Init context and rendering device #if defined(GLES3_ENABLED) @@ -5858,7 +5851,10 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win } WindowID main_window = _create_window(p_mode, p_vsync_mode, p_flags, Rect2i(window_position, p_resolution)); - ERR_FAIL_COND_MSG(main_window == INVALID_WINDOW_ID, "Failed to create main window."); + if (main_window == INVALID_WINDOW_ID) { + r_error = ERR_UNAVAILABLE; + ERR_FAIL_MSG("Failed to create main window."); + } joypad = new JoypadWindows(&windows[MAIN_WINDOW_ID].hWnd); diff --git a/platform/windows/rendering_context_driver_vulkan_windows.cpp b/platform/windows/rendering_context_driver_vulkan_windows.cpp index f968ffc1d785..721794aecb0b 100644 --- a/platform/windows/rendering_context_driver_vulkan_windows.cpp +++ b/platform/windows/rendering_context_driver_vulkan_windows.cpp @@ -55,21 +55,22 @@ RenderingContextDriverVulkanWindows::~RenderingContextDriverVulkanWindows() { // Does nothing. } -RenderingContextDriver::SurfaceID RenderingContextDriverVulkanWindows::surface_create(const void *p_platform_data) { - const WindowPlatformData *wpd = (const WindowPlatformData *)(p_platform_data); +RenderingContextDriver::SurfaceID RenderingContextDriverVulkanWindows::surface_create(Ref p_native_surface) { + Ref windows_native_surface = Object::cast_to(*p_native_surface); + ERR_FAIL_COND_V(windows_native_surface.is_null(), SurfaceID()); VkWin32SurfaceCreateInfoKHR create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; - create_info.hinstance = wpd->instance; - create_info.hwnd = wpd->window; + create_info.hinstance = windows_native_surface->get_instance(); + create_info.hwnd = windows_native_surface->get_window_handle(); VkSurfaceKHR vk_surface = VK_NULL_HANDLE; VkResult err = vkCreateWin32SurfaceKHR(instance_get(), &create_info, nullptr, &vk_surface); ERR_FAIL_COND_V(err != VK_SUCCESS, SurfaceID()); - Surface *surface = memnew(Surface); - surface->vk_surface = vk_surface; - return SurfaceID(surface); + Ref vulkan_surface = RenderingContextDriverVulkan::create(vk_surface); + RenderingContextDriver::SurfaceID result = RenderingContextDriverVulkan::surface_create(vulkan_surface); + return result; } #endif // WINDOWS_ENABLED && VULKAN_ENABLED diff --git a/platform/windows/rendering_context_driver_vulkan_windows.h b/platform/windows/rendering_context_driver_vulkan_windows.h index 1bb70cb0ffad..6e6274afa49e 100644 --- a/platform/windows/rendering_context_driver_vulkan_windows.h +++ b/platform/windows/rendering_context_driver_vulkan_windows.h @@ -34,23 +34,16 @@ #ifdef VULKAN_ENABLED #include "drivers/vulkan/rendering_context_driver_vulkan.h" - -#define WIN32_LEAN_AND_MEAN -#include +#include "servers/rendering/rendering_native_surface.h" class RenderingContextDriverVulkanWindows : public RenderingContextDriverVulkan { private: const char *_get_platform_surface_extension() const override final; protected: - SurfaceID surface_create(const void *p_platform_data) override final; + SurfaceID surface_create(Ref p_native_surface) override final; public: - struct WindowPlatformData { - HWND window; - HINSTANCE instance; - }; - RenderingContextDriverVulkanWindows(); ~RenderingContextDriverVulkanWindows() override; }; diff --git a/platform/windows/rendering_native_surface_windows.cpp b/platform/windows/rendering_native_surface_windows.cpp new file mode 100644 index 000000000000..26cbda840581 --- /dev/null +++ b/platform/windows/rendering_native_surface_windows.cpp @@ -0,0 +1,69 @@ +/**************************************************************************/ +/* rendering_native_surface_windows.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "rendering_native_surface_windows.h" + +void RenderingNativeSurfaceWindows::_bind_methods() { + ClassDB::bind_static_method("RenderingNativeSurfaceWindows", D_METHOD("create", "hwnd", "instance"), &RenderingNativeSurfaceWindows::create_api); +} + +Ref RenderingNativeSurfaceWindows::create(GDExtensionConstPtr p_window, GDExtensionConstPtr p_instance) { + return RenderingNativeSurfaceWindows::create((HWND)p_window.operator const void *(), (HINSTANCE)p_instance.operator const void *()); +} + +Ref RenderingNativeSurfaceWindows::create(HWND p_window, HINSTANCE p_instance) { + Ref result = memnew(RenderingNativeSurfaceWindows); + result->window(p_window); + result->instance(p_instance); + return result; +} + +RenderingContextDriver *RenderingNativeSurfaceWayland::create_rendering_context() { + switch (driver_type) { +#if defined(VULKAN_ENABLED) + case RenderingNativeSurfaceWayland::DriverType::Vulkan: + return memnew(RenderingContextDriverVulkanWindows); +#endif +#if defined(D3D12_ENABLED) + case RenderingNativeSurfaceWayland::DriverType::D3D12: + return memnew(RenderingContextDriverD3D12); +#endif + default: + return nullptr; + } +} + +RenderingNativeSurfaceWindows::RenderingNativeSurfaceWindows() { + // Does nothing. +} + +RenderingNativeSurfaceWindows::~RenderingNativeSurfaceWindows() { + // Does nothing. +} diff --git a/platform/windows/rendering_native_surface_windows.h b/platform/windows/rendering_native_surface_windows.h new file mode 100644 index 000000000000..c62e240cac3a --- /dev/null +++ b/platform/windows/rendering_native_surface_windows.h @@ -0,0 +1,83 @@ +/**************************************************************************/ +/* rendering_native_surface_windows.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef RENDERING_NATIVE_SURFACE_WINDOWS_H +#define RENDERING_NATIVE_SURFACE_WINDOWS_H + +#include "core/variant/native_ptr.h" +#include "servers/rendering/rendering_native_surface.h" + +#define WIN32_LEAN_AND_MEAN +#include + +class RenderingNativeSurfaceWindows : public RenderingNativeSurface { +public: + enum class DriverType { + D3D12, + Vulkan + }; + +private: + GDCLASS(RenderingNativeSurfaceWindows, RenderingNativeSurface); + + static void _bind_methods(); + + HWND window; + HINSTANCE instance; + DriverType driver_type; + +public: + static Ref create_api(GDExtensionConstPtr p_window, GDExtensionConstPtr p_instance); + + static Ref create(HWND p_window, HINSTANCE p_instance); + + HWND get_window_handle() const { + return window; + }; + + HINSTANCE get_instance() const { + return instance; + }; + + void set_driver_type(DriverType p_driver_type) { + driver_type = p_driver_type; + } + + DriverType get_driver_type() { + return driver_type; + } + + RenderingContextDriver *create_rendering_context() override; + + RenderingNativeSurfaceWindows(); + ~RenderingNativeSurfaceWindows(); +}; + +#endif // RENDERING_NATIVE_SURFACE_WINDOWS_H diff --git a/scene/main/window.cpp b/scene/main/window.cpp index d409efbfabd9..76f408e010cb 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -603,6 +603,17 @@ bool Window::is_in_edited_scene_root() const { void Window::_make_window() { ERR_FAIL_COND(window_id != DisplayServer::INVALID_WINDOW_ID); + if (native_surface != nullptr) { + window_id = DisplayServer::get_singleton()->create_native_window(native_surface); + ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID); + + _update_window_size(); + + _update_window_callbacks(); + + RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_WHEN_VISIBLE); + return; + } if (transient && transient_to_focused) { _make_transient(); @@ -675,6 +686,13 @@ void Window::_update_from_window() { void Window::_clear_window() { ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID); + if (native_surface != nullptr) { + DisplayServer::get_singleton()->delete_native_window(window_id); + window_id = DisplayServer::INVALID_WINDOW_ID; + + RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_DISABLED); + return; + } bool had_focus = has_focus(); @@ -835,6 +853,11 @@ void Window::hide() { void Window::set_visible(bool p_visible) { ERR_MAIN_THREAD_GUARD; + if (native_surface.is_valid()) { + visible = true; + return; + } + if (visible == p_visible) { return; } @@ -908,6 +931,29 @@ void Window::_clear_transient() { } } +void Window::set_native_surface(Ref p_native_surface) { + Ref new_native_handle = p_native_surface; + if (new_native_handle == native_surface) { + return; + } + if (!initialized) { + native_surface = new_native_handle; + return; + } + if (embedder) { + embedder->_sub_window_remove(this); + } else { + _clear_window(); + } + native_surface = new_native_handle; + embedder = get_embedder(); + if (embedder) { + embedder->_sub_window_register(this); + } else { + _make_window(); + } +} + void Window::_make_transient() { if (!get_parent()) { //main window, can't be transient @@ -1273,6 +1319,10 @@ Viewport *Window::get_embedder() const { return nullptr; } + if (native_surface != nullptr) { + return nullptr; + } + Viewport *vp = get_parent_viewport(); while (vp) { @@ -2855,6 +2905,8 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("set_visible", "visible"), &Window::set_visible); ClassDB::bind_method(D_METHOD("is_visible"), &Window::is_visible); + ClassDB::bind_method(D_METHOD("set_native_surface", "native_surface"), &Window::set_native_surface); + ClassDB::bind_method(D_METHOD("hide"), &Window::hide); ClassDB::bind_method(D_METHOD("show"), &Window::show); diff --git a/scene/main/window.h b/scene/main/window.h index 33d593711f23..4ca9f99f0ca5 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -33,6 +33,7 @@ #include "scene/main/viewport.h" #include "scene/resources/theme.h" +#include "servers/rendering/rendering_native_surface.h" class Font; class Shortcut; @@ -164,6 +165,8 @@ class Window : public Viewport { void _update_window_callbacks(); + Ref native_surface; + Window *transient_parent = nullptr; Window *exclusive_child = nullptr; HashSet transient_children; @@ -315,6 +318,8 @@ class Window : public Viewport { virtual void set_visible(bool p_visible); bool is_visible() const; + void set_native_surface(Ref p_native_surface); + void update_mouse_cursor_state() override; void show(); diff --git a/servers/SCsub b/servers/SCsub index 736bed68ecb2..bd6363f67fd5 100644 --- a/servers/SCsub +++ b/servers/SCsub @@ -7,6 +7,7 @@ env.servers_sources = [] env.add_source_files(env.servers_sources, "audio_server.cpp") env.add_source_files(env.servers_sources, "camera_server.cpp") env.add_source_files(env.servers_sources, "display_server.cpp") +env.add_source_files(env.servers_sources, "display_server_embedded.cpp") env.add_source_files(env.servers_sources, "navigation_server_2d.cpp") env.add_source_files(env.servers_sources, "navigation_server_3d.cpp") env.add_source_files(env.servers_sources, "physics_server_2d.cpp") diff --git a/servers/display_server.cpp b/servers/display_server.cpp index b6e0d58af744..8e9a68da06cc 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -574,6 +574,18 @@ DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, VSyn ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Sub-windows not supported by this display server."); } +DisplayServer::WindowID DisplayServer::create_native_window(Ref p_native_window) { + ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Native windows not supported by this display server."); +} + +bool DisplayServer::is_native_window(DisplayServer::WindowID p_id) { + ERR_FAIL_V_MSG(false, "Native windows not supported by this display server."); +} + +void DisplayServer::delete_native_window(DisplayServer::WindowID p_id) { + ERR_FAIL_MSG("Native windows not supported by this display server."); +} + void DisplayServer::show_window(WindowID p_id) { ERR_FAIL_MSG("Sub-windows not supported by this display server."); } diff --git a/servers/display_server.h b/servers/display_server.h index 5d82b6c13c92..0f94c824ea6a 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -35,8 +35,8 @@ #include "core/io/resource.h" #include "core/os/os.h" #include "core/variant/callable.h" - #include "display/native_menu.h" +#include "servers/rendering/rendering_native_surface.h" class Texture2D; class Image; @@ -148,6 +148,7 @@ class DisplayServer : public Object { FEATURE_NATIVE_HELP, FEATURE_NATIVE_DIALOG_INPUT, FEATURE_NATIVE_DIALOG_FILE, + FEATURE_NATIVE_WINDOWS, }; virtual bool has_feature(Feature p_feature) const = 0; @@ -398,6 +399,10 @@ class DisplayServer : public Object { virtual void show_window(WindowID p_id); virtual void delete_sub_window(WindowID p_id); + virtual WindowID create_native_window(Ref p_native_window); + virtual bool is_native_window(WindowID p_id); + virtual void delete_native_window(WindowID p_id); + virtual WindowID window_get_active_popup() const { return INVALID_WINDOW_ID; } virtual void window_set_popup_safe_rect(WindowID p_window, const Rect2i &p_rect) {} virtual Rect2i window_get_popup_safe_rect(WindowID p_window) const { return Rect2i(); } diff --git a/servers/display_server_embedded.cpp b/servers/display_server_embedded.cpp new file mode 100644 index 000000000000..f3261ddc6789 --- /dev/null +++ b/servers/display_server_embedded.cpp @@ -0,0 +1,540 @@ +/**************************************************************************/ +/* display_server_embedded.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "display_server_embedded.h" + +#include "core/config/project_settings.h" +#include "core/io/file_access_pack.h" + +#ifdef RD_ENABLED +#if defined(VULKAN_ENABLED) +#include "drivers/vulkan/rendering_context_driver_vulkan_moltenvk.h" + +#ifdef USE_VOLK +#include +#else +#include +#endif +#endif // VULKAN_ENABLED +#endif // RD_ENABLED + +#include "drivers/apple/rendering_native_surface_apple.h" + +Ref DisplayServerEmbedded::native_surface = nullptr; + +DisplayServerEmbedded *DisplayServerEmbedded::get_singleton() { + return (DisplayServerEmbedded *)DisplayServer::get_singleton(); +} + +void DisplayServerEmbedded::set_native_surface(Ref p_native_surface) { + native_surface = p_native_surface; +} + +void DisplayServerEmbedded::_bind_methods() { + ClassDB::bind_static_method("DisplayServerEmbedded", D_METHOD("set_native_surface", "native_surface"), &DisplayServerEmbedded::set_native_surface); + ClassDB::bind_method(D_METHOD("resize_window", "size", "id"), &DisplayServerEmbedded::resize_window); + ClassDB::bind_method(D_METHOD("set_content_scale", "content_scale"), &DisplayServerEmbedded::set_content_scale); + ClassDB::bind_method(D_METHOD("touch_press", "idx", "x", "y", "pressed", "double_click", "window"), &DisplayServerEmbedded::touch_press); + ClassDB::bind_method(D_METHOD("touch_drag", "idx", "prev_x", "prev_y", "x", "y", "pressure", "tilt", "window"), &DisplayServerEmbedded::touch_drag); + ClassDB::bind_method(D_METHOD("touches_canceled", "idx", "window"), &DisplayServerEmbedded::touches_canceled); + ClassDB::bind_method(D_METHOD("key", "key", "char", "unshifted", "physical", "modifiers", "pressed", "window"), &DisplayServerEmbedded::key, DEFVAL(MAIN_WINDOW_ID)); +} + +DisplayServerEmbedded::DisplayServerEmbedded(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::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) { + ERR_FAIL_NULL_MSG(native_surface, "Native surface has not been set."); + + rendering_driver = p_rendering_driver; + + native_menu = memnew(NativeMenu); + +#if defined(RD_ENABLED) + rendering_context = nullptr; + rendering_device = nullptr; + +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { + rendering_context = native_surface->create_rendering_context(); + } +#endif + + if (rendering_context) { + if (rendering_context->initialize() != OK) { + ERR_PRINT(vformat("Failed to initialize %s context", rendering_driver)); + memdelete(rendering_context); + rendering_context = nullptr; + return; + } + + if (create_native_window(native_surface) != MAIN_WINDOW_ID) { + ERR_PRINT(vformat("Failed to create %s window.", rendering_driver)); + memdelete(rendering_context); + rendering_context = nullptr; + r_error = ERR_UNAVAILABLE; + return; + } + + rendering_device = memnew(RenderingDevice); + rendering_device->initialize(rendering_context, MAIN_WINDOW_ID); + rendering_device->screen_create(MAIN_WINDOW_ID); + + RendererCompositorRD::make_current(); + } +#endif + +#if defined(GLES3_ENABLED) + if (rendering_driver == "opengl3") { + ERR_FAIL_MSG("Embedded OpenGL rendering is not yet supported."); + } +#endif + + Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events); + + r_error = OK; +} + +DisplayServerEmbedded::~DisplayServerEmbedded() { + if (native_menu) { + memdelete(native_menu); + native_menu = nullptr; + } + +#if defined(RD_ENABLED) + if (rendering_device) { + rendering_device->screen_free(MAIN_WINDOW_ID); + memdelete(rendering_device); + rendering_device = nullptr; + } + + if (rendering_context) { + rendering_context->window_destroy(MAIN_WINDOW_ID); + memdelete(rendering_context); + rendering_context = nullptr; + } +#endif +} + +DisplayServer *DisplayServerEmbedded::create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::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) { + return memnew(DisplayServerEmbedded(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, p_context, r_error)); +} + +Vector DisplayServerEmbedded::get_rendering_drivers_func() { + Vector drivers; + +#if defined(VULKAN_ENABLED) + drivers.push_back("vulkan"); +#endif + //#if defined(GLES3_ENABLED) + // drivers.push_back("opengl3"); + //#endif + + return drivers; +} + +void DisplayServerEmbedded::register_embedded_driver() { + register_create_function("embedded", create_func, get_rendering_drivers_func); +} + +// MARK: Events + +void DisplayServerEmbedded::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) { + window_resize_callbacks[p_window] = p_callable; +} + +void DisplayServerEmbedded::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) { + window_event_callbacks[p_window] = p_callable; +} +void DisplayServerEmbedded::window_set_input_event_callback(const Callable &p_callable, WindowID p_window) { + input_event_callbacks[p_window] = p_callable; +} + +void DisplayServerEmbedded::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) { + input_text_callbacks[p_window] = p_callable; +} + +void DisplayServerEmbedded::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) { + // Not supported +} + +void DisplayServerEmbedded::process_events() { + Input::get_singleton()->flush_buffered_events(); +} + +void DisplayServerEmbedded::_dispatch_input_events(const Ref &p_event) { + Ref event_from_window = p_event; + WindowID window_id = INVALID_WINDOW_ID; + if (event_from_window.is_valid()) { + window_id = event_from_window->get_window_id(); + } + DisplayServerEmbedded::get_singleton()->send_input_event(p_event, window_id); +} + +void DisplayServerEmbedded::send_input_event(const Ref &p_event, WindowID p_id) const { + if (p_id != INVALID_WINDOW_ID) { + _window_callback(input_event_callbacks[p_id], p_event); + } else { + for (const KeyValue &E : input_event_callbacks) { + _window_callback(E.value, p_event); + } + } +} + +void DisplayServerEmbedded::send_input_text(const String &p_text, WindowID p_id) const { + _window_callback(input_text_callbacks[p_id], p_text); +} + +void DisplayServerEmbedded::send_window_event(DisplayServer::WindowEvent p_event, WindowID p_id) const { + _window_callback(window_event_callbacks[p_id], int(p_event)); +} + +void DisplayServerEmbedded::_window_callback(const Callable &p_callable, const Variant &p_arg) const { + if (!p_callable.is_null()) { + p_callable.call(p_arg); + } +} + +// MARK: - Input + +// MARK: Touches + +void DisplayServerEmbedded::touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click, DisplayServer::WindowID p_window) { + Ref ev; + ev.instantiate(); + + ev->set_window_id(p_window); + ev->set_index(p_idx); + ev->set_pressed(p_pressed); + ev->set_position(Vector2(p_x, p_y)); + ev->set_double_tap(p_double_click); + perform_event(ev); +} + +void DisplayServerEmbedded::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y, float p_pressure, Vector2 p_tilt, DisplayServer::WindowID p_window) { + Ref ev; + ev.instantiate(); + ev->set_window_id(p_window); + ev->set_index(p_idx); + ev->set_pressure(p_pressure); + ev->set_tilt(p_tilt); + ev->set_position(Vector2(p_x, p_y)); + ev->set_relative(Vector2(p_x - p_prev_x, p_y - p_prev_y)); + ev->set_relative_screen_position(ev->get_relative()); + perform_event(ev); +} + +void DisplayServerEmbedded::perform_event(const Ref &p_event) { + Input::get_singleton()->parse_input_event(p_event); +} + +void DisplayServerEmbedded::touches_canceled(int p_idx, DisplayServer::WindowID p_window) { + touch_press(p_idx, -1, -1, false, false, p_window); +} + +void DisplayServerEmbedded::key(Key p_key, char32_t p_char, Key p_unshifted, Key p_physical, BitField p_modifiers, bool p_pressed, DisplayServer::WindowID p_window) { + Ref ev; + ev.instantiate(); + ev->set_window_id(p_window); + ev->set_echo(false); + ev->set_pressed(p_pressed); + ev->set_keycode(fix_keycode(p_char, p_key)); + if (p_key != Key::SHIFT) { + ev->set_shift_pressed(p_modifiers.has_flag(KeyModifierMask::SHIFT)); + } + if (p_key != Key::CTRL) { + ev->set_ctrl_pressed(p_modifiers.has_flag(KeyModifierMask::CTRL)); + } + if (p_key != Key::ALT) { + ev->set_alt_pressed(p_modifiers.has_flag(KeyModifierMask::ALT)); + } + if (p_key != Key::META) { + ev->set_meta_pressed(p_modifiers.has_flag(KeyModifierMask::META)); + } + ev->set_key_label(p_unshifted); + ev->set_physical_keycode(p_physical); + ev->set_unicode(fix_unicode(p_char)); + perform_event(ev); +} + +// MARK: - + +bool DisplayServerEmbedded::has_feature(Feature p_feature) const { + switch (p_feature) { +#ifndef DISABLE_DEPRECATED + case FEATURE_GLOBAL_MENU: { + return (native_menu && native_menu->has_feature(NativeMenu::FEATURE_GLOBAL_MENU)); + } break; +#endif + // case FEATURE_CURSOR_SHAPE: + // case FEATURE_CUSTOM_CURSOR_SHAPE: + // case FEATURE_HIDPI: + // case FEATURE_ICON: + // case FEATURE_IME: + // case FEATURE_MOUSE: + // case FEATURE_MOUSE_WARP: + // case FEATURE_NATIVE_DIALOG: + // case FEATURE_NATIVE_ICON: + // case FEATURE_WINDOW_TRANSPARENCY: + //case FEATURE_CLIPBOARD: + //case FEATURE_KEEP_SCREEN_ON: + //case FEATURE_ORIENTATION: + //case FEATURE_VIRTUAL_KEYBOARD: + //case FEATURE_TEXT_TO_SPEECH: + case FEATURE_NATIVE_WINDOWS: + case FEATURE_TOUCHSCREEN: + return true; + default: + return false; + } +} + +String DisplayServerEmbedded::get_name() const { + return "embedded"; +} + +int DisplayServerEmbedded::get_screen_count() const { + return 1; +} + +int DisplayServerEmbedded::get_primary_screen() const { + return 0; +} + +Point2i DisplayServerEmbedded::screen_get_position(int p_screen) const { + return Size2i(); +} + +Size2i DisplayServerEmbedded::screen_get_size(int p_screen) const { + return window_get_size(MAIN_WINDOW_ID); +} + +Rect2i DisplayServerEmbedded::screen_get_usable_rect(int p_screen) const { + return Rect2i(screen_get_position(p_screen), screen_get_size(p_screen)); +} + +int DisplayServerEmbedded::screen_get_dpi(int p_screen) const { + return 96; +} + +float DisplayServerEmbedded::screen_get_refresh_rate(int p_screen) const { + return -1; +} + +Vector DisplayServerEmbedded::get_window_list() const { + Vector list; + list.push_back(MAIN_WINDOW_ID); + return list; +} + +DisplayServer::WindowID DisplayServerEmbedded::get_window_at_screen_position(const Point2i &p_position) const { + return MAIN_WINDOW_ID; +} + +DisplayServer::WindowID DisplayServerEmbedded::create_native_window(Ref p_native_surface) { +#if defined(RD_ENABLED) + + WindowID window_id = window_id_counter++; + + if (rendering_context->window_create(window_id, p_native_surface) != OK) { + ERR_PRINT(vformat("Failed to create native window.")); + return INVALID_WINDOW_ID; + } + + if (rendering_device) { + rendering_device->screen_create(window_id); + } + return window_id; +#else + ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Cannot create native window with current driver."); +#endif +} + +bool DisplayServerEmbedded::is_native_window(DisplayServer::WindowID p_id) { + return true; +} + +void DisplayServerEmbedded::delete_native_window(DisplayServer::WindowID p_id) { +#if defined(RD_ENABLED) + if (rendering_device) { + rendering_device->screen_free(p_id); + } + + if (rendering_context) { + rendering_context->window_destroy(p_id); + } +#endif +} + +int64_t DisplayServerEmbedded::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { + return 0; // Not supported. +} + +void DisplayServerEmbedded::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { + window_attached_instance_id[p_window] = p_instance; +} + +ObjectID DisplayServerEmbedded::window_get_attached_instance_id(WindowID p_window) const { + return window_attached_instance_id[p_window]; +} + +void DisplayServerEmbedded::window_set_title(const String &p_title, WindowID p_window) { + // Not supported +} + +int DisplayServerEmbedded::window_get_current_screen(WindowID p_window) const { + return SCREEN_OF_MAIN_WINDOW; +} + +void DisplayServerEmbedded::window_set_current_screen(int p_screen, WindowID p_window) { + // Not supported +} + +Point2i DisplayServerEmbedded::window_get_position(WindowID p_window) const { + return Point2i(); +} + +Point2i DisplayServerEmbedded::window_get_position_with_decorations(WindowID p_window) const { + return Point2i(); +} + +void DisplayServerEmbedded::window_set_position(const Point2i &p_position, WindowID p_window) { + // Probably not supported for single window iOS app +} + +void DisplayServerEmbedded::window_set_transient(WindowID p_window, WindowID p_parent) { + // Not supported +} + +void DisplayServerEmbedded::window_set_max_size(const Size2i p_size, WindowID p_window) { + // Not supported +} + +Size2i DisplayServerEmbedded::window_get_max_size(WindowID p_window) const { + return Size2i(); +} + +void DisplayServerEmbedded::window_set_min_size(const Size2i p_size, WindowID p_window) { + // Not supported +} + +Size2i DisplayServerEmbedded::window_get_min_size(WindowID p_window) const { + return Size2i(); +} + +void DisplayServerEmbedded::window_set_size(const Size2i p_size, WindowID p_window) { + // Not supported +} + +Size2i DisplayServerEmbedded::window_get_size(WindowID p_window) const { +#if defined(RD_ENABLED) + if (rendering_context) { + uint32_t width = 0; + uint32_t height = 0; + rendering_context->window_get_size(p_window, width, height); + return Size2i(width, height); + } +#endif + return Size2i(); +} + +Size2i DisplayServerEmbedded::window_get_size_with_decorations(WindowID p_window) const { + return window_get_size(p_window); +} + +void DisplayServerEmbedded::window_set_mode(WindowMode p_mode, WindowID p_window) { + // Not supported +} + +DisplayServer::WindowMode DisplayServerEmbedded::window_get_mode(WindowID p_window) const { + return WindowMode::WINDOW_MODE_FULLSCREEN; +} + +bool DisplayServerEmbedded::window_is_maximize_allowed(WindowID p_window) const { + return false; +} + +void DisplayServerEmbedded::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) { + // Not supported +} + +bool DisplayServerEmbedded::window_get_flag(WindowFlags p_flag, WindowID p_window) const { + return false; +} + +void DisplayServerEmbedded::window_request_attention(WindowID p_window) { + // Not supported +} + +void DisplayServerEmbedded::window_move_to_foreground(WindowID p_window) { + // Not supported +} + +bool DisplayServerEmbedded::window_is_focused(WindowID p_window) const { + return true; +} + +float DisplayServerEmbedded::screen_get_max_scale() const { + return screen_get_scale(SCREEN_OF_MAIN_WINDOW); +} + +bool DisplayServerEmbedded::window_can_draw(WindowID p_window) const { + return true; +} + +bool DisplayServerEmbedded::can_any_window_draw() const { + return true; +} + +bool DisplayServerEmbedded::is_touchscreen_available() const { + return true; +} + +void DisplayServerEmbedded::resize_window(Size2i p_size, WindowID p_id) { + Size2i size = p_size * content_scale; + +#if defined(RD_ENABLED) + if (rendering_context) { + rendering_context->window_set_size(p_id, size.x, size.y); + } +#endif + + Variant resize_rect = Rect2i(Point2i(), size); + _window_callback(window_resize_callbacks[p_id], resize_rect); +} + +void DisplayServerEmbedded::set_content_scale(float p_scale) { + content_scale = p_scale; +} + +void DisplayServerEmbedded::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) { + // Not supported +} + +DisplayServer::VSyncMode DisplayServerEmbedded::window_get_vsync_mode(WindowID p_window) const { + return DisplayServer::VSYNC_ENABLED; +} diff --git a/servers/display_server_embedded.h b/servers/display_server_embedded.h new file mode 100644 index 000000000000..3c18142018dc --- /dev/null +++ b/servers/display_server_embedded.h @@ -0,0 +1,194 @@ +/**************************************************************************/ +/* display_server_embedded.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef DISPLAY_SERVER_EMBEDDED_H +#define DISPLAY_SERVER_EMBEDDED_H + +#include "core/input/input.h" +#include "servers/display_server.h" + +#if defined(RD_ENABLED) +#include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/rendering_device.h" +#endif + +#if defined(GLES3_ENABLED) +#include "drivers/gles3/rasterizer_gles3.h" +#endif // GLES3_ENABLED + +class DisplayServerEmbedded : public DisplayServer { + GDCLASS(DisplayServerEmbedded, DisplayServer) + + _THREAD_SAFE_CLASS_ + +#if defined(RD_ENABLED) + RenderingContextDriver *rendering_context = nullptr; + RenderingDevice *rendering_device = nullptr; +#endif + NativeMenu *native_menu = nullptr; + + DisplayServer::ScreenOrientation screen_orientation; + + HashMap window_attached_instance_id; + + HashMap window_event_callbacks; + HashMap window_resize_callbacks; + HashMap input_event_callbacks; + HashMap input_text_callbacks; + + float content_scale = 1.0f; + + WindowID window_id_counter = MAIN_WINDOW_ID; + + void perform_event(const Ref &p_event); + + static Ref native_surface; + + DisplayServerEmbedded(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::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); + ~DisplayServerEmbedded(); + +protected: + static void _bind_methods(); + +public: + String rendering_driver; + + static DisplayServerEmbedded *get_singleton(); + + static void set_native_surface(Ref p_native_handle); + + static void register_embedded_driver(); + static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::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); + static Vector get_rendering_drivers_func(); + + // MARK: - Events + + virtual void process_events() override; + + virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override; + virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override; + virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override; + virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override; + virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override; + + static void _dispatch_input_events(const Ref &p_event); + void send_input_event(const Ref &p_event, DisplayServer::WindowID p_id = MAIN_WINDOW_ID) const; + void send_input_text(const String &p_text, DisplayServer::WindowID p_id = MAIN_WINDOW_ID) const; + void send_window_event(DisplayServer::WindowEvent p_event, DisplayServer::WindowID p_id = MAIN_WINDOW_ID) const; + void _window_callback(const Callable &p_callable, const Variant &p_arg) const; + + // MARK: - Input + + // MARK: Touches and Apple Pencil + + void touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click, DisplayServer::WindowID p_window); + void touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y, float p_pressure, Vector2 p_tilt, DisplayServer::WindowID p_window); + void touches_canceled(int p_idx, DisplayServer::WindowID p_window); + + // MARK: Keyboard + + void key(Key p_key, char32_t p_char, Key p_unshifted, Key p_physical, BitField p_modifiers, bool p_pressed, DisplayServer::WindowID p_window = MAIN_WINDOW_ID); + + // MARK: - + + virtual bool has_feature(Feature p_feature) const override; + virtual String get_name() const override; + + virtual int get_screen_count() const override; + virtual int get_primary_screen() const override; + virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; + virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; + virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; + virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; + virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; + + virtual Vector get_window_list() const override; + + virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override; + + virtual WindowID create_native_window(Ref p_native_window) override; + virtual bool is_native_window(WindowID p_id) override; + virtual void delete_native_window(WindowID p_id) override; + + virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override; + + virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override; + virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override; + + virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override; + + virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override; + virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override; + + virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override; + virtual Point2i window_get_position_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const override; + virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override; + + virtual void window_set_transient(WindowID p_window, WindowID p_parent) override; + + virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override; + virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override; + + virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override; + virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override; + + virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override; + virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override; + virtual Size2i window_get_size_with_decorations(WindowID p_window = MAIN_WINDOW_ID) const override; + + virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override; + virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override; + + virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const override; + + virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override; + virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override; + + virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override; + virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override; + virtual bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const override; + + virtual float screen_get_max_scale() const override; + + virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override; + + virtual bool can_any_window_draw() const override; + + virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override; + virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override; + + virtual bool is_touchscreen_available() const override; + + void resize_window(Size2i size, WindowID p_id); + void set_content_scale(float p_scale); + virtual void swap_buffers() override {} +}; + +#endif // DISPLAY_SERVER_EMBEDDED_H diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index fc2aae10c7ab..d43953b5d0fa 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -59,6 +59,7 @@ #include "debugger/servers_debugger.h" #include "display/native_menu.h" #include "display_server.h" +#include "display_server_embedded.h" #include "movie_writer/movie_writer.h" #include "movie_writer/movie_writer_mjpeg.h" #include "movie_writer/movie_writer_pngwav.h" @@ -70,6 +71,7 @@ #include "rendering/renderer_rd/uniform_set_cache_rd.h" #include "rendering/rendering_device.h" #include "rendering/rendering_device_binds.h" +#include "rendering/rendering_native_surface.h" #include "rendering/storage/render_data.h" #include "rendering/storage/render_scene_buffers.h" #include "rendering/storage/render_scene_data.h" @@ -144,6 +146,16 @@ static bool has_server_feature_callback(const String &p_feature) { static MovieWriterMJPEG *writer_mjpeg = nullptr; static MovieWriterPNGWAV *writer_pngwav = nullptr; +void register_core_server_types() { + OS::get_singleton()->benchmark_begin_measure("Servers", "Register Core Extensions"); + GDREGISTER_ABSTRACT_CLASS(DisplayServer); + GDREGISTER_ABSTRACT_CLASS(DisplayServerEmbedded); + OS::get_singleton()->benchmark_end_measure("Servers", "Register Core Extensions"); +} + +void unregister_core_server_types() { +} + void register_server_types() { OS::get_singleton()->benchmark_begin_measure("Servers", "Register Extensions"); @@ -161,7 +173,6 @@ void register_server_types() { OS::get_singleton()->set_has_server_feature_callback(has_server_feature_callback); - GDREGISTER_ABSTRACT_CLASS(DisplayServer); GDREGISTER_ABSTRACT_CLASS(RenderingServer); GDREGISTER_CLASS(AudioServer); @@ -243,6 +254,8 @@ void register_server_types() { GDREGISTER_CLASS(RDShaderFile); GDREGISTER_CLASS(RDPipelineSpecializationConstant); + GDREGISTER_ABSTRACT_CLASS(RenderingNativeSurface); + GDREGISTER_ABSTRACT_CLASS(RenderData); GDREGISTER_CLASS(RenderDataExtension); GDREGISTER_CLASS(RenderDataRD); diff --git a/servers/register_server_types.h b/servers/register_server_types.h index 9cf546ba9223..a7abfb71e137 100644 --- a/servers/register_server_types.h +++ b/servers/register_server_types.h @@ -31,6 +31,9 @@ #ifndef REGISTER_SERVER_TYPES_H #define REGISTER_SERVER_TYPES_H +void register_core_server_types(); +void unregister_core_server_types(); + void register_server_types(); void unregister_server_types(); diff --git a/servers/rendering/rendering_context_driver.cpp b/servers/rendering/rendering_context_driver.cpp index 19c0b0838c80..f7049f97829d 100644 --- a/servers/rendering/rendering_context_driver.cpp +++ b/servers/rendering/rendering_context_driver.cpp @@ -42,8 +42,8 @@ RenderingContextDriver::SurfaceID RenderingContextDriver::surface_get_from_windo } } -Error RenderingContextDriver::window_create(DisplayServer::WindowID p_window, const void *p_platform_data) { - SurfaceID surface = surface_create(p_platform_data); +Error RenderingContextDriver::window_create(DisplayServer::WindowID p_window, Ref p_native_surface) { + SurfaceID surface = surface_create(p_native_surface); if (surface != 0) { window_surface_map[p_window] = surface; return OK; @@ -59,6 +59,14 @@ void RenderingContextDriver::window_set_size(DisplayServer::WindowID p_window, u } } +void RenderingContextDriver::window_get_size(DisplayServer::WindowID p_window, uint32_t &r_width, uint32_t &r_height) { + SurfaceID surface = surface_get_from_window(p_window); + if (surface) { + r_width = surface_get_width(surface); + r_height = surface_get_height(surface); + } +} + void RenderingContextDriver::window_set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_vsync_mode) { SurfaceID surface = surface_get_from_window(p_window); if (surface) { diff --git a/servers/rendering/rendering_context_driver.h b/servers/rendering/rendering_context_driver.h index 539b3814a041..21454169c73c 100644 --- a/servers/rendering/rendering_context_driver.h +++ b/servers/rendering/rendering_context_driver.h @@ -32,6 +32,7 @@ #define RENDERING_CONTEXT_DRIVER_H #include "core/object/object.h" +#include "rendering_native_surface.h" #include "servers/display_server.h" class RenderingDeviceDriver; @@ -45,8 +46,9 @@ class RenderingContextDriver { public: SurfaceID surface_get_from_window(DisplayServer::WindowID p_window) const; - Error window_create(DisplayServer::WindowID p_window, const void *p_platform_data); + Error window_create(DisplayServer::WindowID p_window, Ref p_native_surface); void window_set_size(DisplayServer::WindowID p_window, uint32_t p_width, uint32_t p_height); + void window_get_size(DisplayServer::WindowID p_window, uint32_t &r_width, uint32_t &r_height); void window_set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_vsync_mode); DisplayServer::VSyncMode window_get_vsync_mode(DisplayServer::WindowID p_window) const; void window_destroy(DisplayServer::WindowID p_window); @@ -91,7 +93,7 @@ class RenderingContextDriver { virtual bool device_supports_present(uint32_t p_device_index, SurfaceID p_surface) const = 0; virtual RenderingDeviceDriver *driver_create() = 0; virtual void driver_free(RenderingDeviceDriver *p_driver) = 0; - virtual SurfaceID surface_create(const void *p_platform_data) = 0; + virtual SurfaceID surface_create(Ref p_native_surface) = 0; virtual void surface_set_size(SurfaceID p_surface, uint32_t p_width, uint32_t p_height) = 0; virtual void surface_set_vsync_mode(SurfaceID p_surface, DisplayServer::VSyncMode p_vsync_mode) = 0; virtual DisplayServer::VSyncMode surface_get_vsync_mode(SurfaceID p_surface) const = 0; diff --git a/servers/rendering/rendering_native_surface.cpp b/servers/rendering/rendering_native_surface.cpp new file mode 100644 index 000000000000..1fd8ceef6e17 --- /dev/null +++ b/servers/rendering/rendering_native_surface.cpp @@ -0,0 +1,40 @@ +/**************************************************************************/ +/* rendering_native_surface.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "rendering_native_surface.h" + +void RenderingNativeSurface::_bind_methods() { +} + +RenderingNativeSurface::RenderingNativeSurface() { +} + +RenderingNativeSurface::~RenderingNativeSurface() { +} diff --git a/servers/rendering/rendering_native_surface.h b/servers/rendering/rendering_native_surface.h new file mode 100644 index 000000000000..d31aea71ff14 --- /dev/null +++ b/servers/rendering/rendering_native_surface.h @@ -0,0 +1,51 @@ +/**************************************************************************/ +/* rendering_native_surface.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef RENDERING_NATIVE_SURFACE_H +#define RENDERING_NATIVE_SURFACE_H + +#include "core/object/class_db.h" +#include "core/object/ref_counted.h" + +class RenderingContextDriver; + +class RenderingNativeSurface : public RefCounted { + GDCLASS(RenderingNativeSurface, RefCounted); + + static void _bind_methods(); + +public: + RenderingNativeSurface(); + ~RenderingNativeSurface(); + + virtual RenderingContextDriver *create_rendering_context() = 0; +}; + +#endif // RENDERING_NATIVE_SURFACE_H