From 25ff7af1611280f7169fe1b82f9a11801f274849 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Sat, 21 Oct 2023 12:59:14 +0200 Subject: [PATCH] Allow applications to customize how the global managers are initialized. --- application/CMakeLists.txt | 9 +++ application/application.cpp | 10 +-- application/application.hpp | 20 +----- application/application_entry.cpp | 8 ++- application/application_glue.hpp | 68 +++++++++++++++++++ application/application_interface_query.cpp | 2 + application/platforms/application_android.cpp | 5 +- application/platforms/application_glfw.cpp | 8 ++- .../platforms/application_headless.cpp | 24 ++++--- .../platforms/application_khr_display.cpp | 9 ++- .../platforms/application_libretro.cpp | 4 +- 11 files changed, 126 insertions(+), 41 deletions(-) create mode 100644 application/application_glue.hpp create mode 100644 application/application_interface_query.cpp diff --git a/application/CMakeLists.txt b/application/CMakeLists.txt index bea5b6ad6..83e0b9bec 100644 --- a/application/CMakeLists.txt +++ b/application/CMakeLists.txt @@ -1,5 +1,6 @@ add_granite_internal_lib(granite-application application.hpp + application_glue.hpp application.cpp platforms/application_headless.cpp) @@ -42,6 +43,14 @@ target_link_libraries(granite-application-entry-headless PRIVATE granite-application granite-platform granite-filesystem) target_compile_options(granite-application-entry-headless PRIVATE ${GRANITE_CXX_FLAGS}) +# Can be defined by application to get a custom entry point. +# Otherwise, get a default one. +if (NOT TARGET granite-application-interface-query) + add_granite_internal_lib(granite-application-interface-query STATIC application_interface_query.cpp) + target_compile_options(granite-application-interface-query PRIVATE ${GRANITE_CXX_FLAGS}) +endif() +target_link_libraries(granite-application PRIVATE granite-application-interface-query) + add_subdirectory(events) add_subdirectory(input) add_subdirectory(platforms) diff --git a/application/application.cpp b/application/application.cpp index 15b054f5e..6f60ddc50 100644 --- a/application/application.cpp +++ b/application/application.cpp @@ -35,13 +35,6 @@ using namespace Vulkan; namespace Granite { -Application::Application() -{ -#ifdef HAVE_GRANITE_RENDERER - GRANITE_COMMON_RENDERER_DATA()->initialize_static_assets(GRANITE_ASSET_MANAGER(), GRANITE_FILESYSTEM()); -#endif -} - Application::~Application() { auto *group = GRANITE_THREAD_GROUP(); @@ -53,6 +46,9 @@ Application::~Application() bool Application::init_platform(std::unique_ptr new_platform) { +#ifdef HAVE_GRANITE_RENDERER + GRANITE_COMMON_RENDERER_DATA()->initialize_static_assets(GRANITE_ASSET_MANAGER(), GRANITE_FILESYSTEM()); +#endif platform = std::move(new_platform); application_wsi.set_platform(platform.get()); return true; diff --git a/application/application.hpp b/application/application.hpp index 4b9a128e0..fce6fa6d7 100644 --- a/application/application.hpp +++ b/application/application.hpp @@ -24,13 +24,13 @@ #include "wsi.hpp" #include "application_wsi_events.hpp" #include "input.hpp" +#include "application_glue.hpp" namespace Granite { class Application { public: - Application(); virtual ~Application(); virtual void render_frame(double frame_time, double elapsed_time) = 0; bool init_platform(std::unique_ptr platform); @@ -100,20 +100,4 @@ class Application bool ready_pipelines = false; void check_initialization_progress(); }; - -int application_main(Application *(*create_application)(int, char **), int argc, char **argv); -int application_main_headless(Application *(*create_application)(int, char **), int argc, char **argv); - -extern Application *application_create(int argc, char *argv[]); - -// Call this or setup_default_filesystem to ensure application-main is linked in correctly without having to mess around -// with -Wl,--whole-archive. -void application_dummy(); -void application_setup_default_filesystem(const char *default_asset_directory); -} - -#ifdef ASSET_DIRECTORY -#define GRANITE_APPLICATION_SETUP_FILESYSTEM() ::Granite::application_setup_default_filesystem(ASSET_DIRECTORY) -#else -#define GRANITE_APPLICATION_SETUP_FILESYSTEM() ::Granite::application_setup_default_filesystem(nullptr) -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/application/application_entry.cpp b/application/application_entry.cpp index 88d1d6a06..6e3f3bda5 100644 --- a/application/application_entry.cpp +++ b/application/application_entry.cpp @@ -86,9 +86,13 @@ int main(int argc, char *argv[]) #endif #ifdef APPLICATION_ENTRY_HEADLESS - int ret = Granite::application_main_headless(Granite::application_create, argc, argv); + int ret = Granite::application_main_headless(Granite::query_application_interface, + Granite::application_create, + argc, argv); #else - int ret = Granite::application_main(Granite::application_create, argc, argv); + int ret = Granite::application_main(Granite::query_application_interface, + Granite::application_create, + argc, argv); #endif return ret; diff --git a/application/application_glue.hpp b/application/application_glue.hpp new file mode 100644 index 000000000..339db1d2d --- /dev/null +++ b/application/application_glue.hpp @@ -0,0 +1,68 @@ +/* Copyright (c) 2017-2023 Hans-Kristian Arntzen + * + * 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. + */ + +#pragma once +#include +#include + +namespace Granite +{ +enum class ApplicationQuery +{ + DefaultManagerFlags +}; + +class Application; + +int application_main( + bool (*query_application_interface)(ApplicationQuery, void *data, size_t size), + Application *(*create_application)(int, char **), + int argc, char **argv); + +int application_main_headless( + bool (*query_application_interface)(ApplicationQuery, void *data, size_t size), + Application *(*create_application)(int, char **), + int argc, char **argv); + +extern Application *application_create(int argc, char *argv[]); + +struct ApplicationQueryDefaultManagerFlags +{ + uint32_t manager_feature_flags; +}; + +extern bool query_application_interface(ApplicationQuery query, void *data, size_t size); + +// Call this or setup_default_filesystem to ensure application-main is linked in correctly without having to mess around +// with -Wl,--whole-archive. +void application_dummy(); + +void application_setup_default_filesystem(const char *default_asset_directory); +} + +#ifdef ASSET_DIRECTORY +#define GRANITE_APPLICATION_SETUP_FILESYSTEM() ::Granite::application_setup_default_filesystem(ASSET_DIRECTORY) +#else +#define GRANITE_APPLICATION_SETUP_FILESYSTEM() ::Granite::application_setup_default_filesystem(nullptr) +#endif + +#define GRANITE_APPLICATION_DECL_DEFAULT_QUERY() namespace Granite { bool query_application_interface(Granite::ApplicationQuery, void *, size_t) { return false; } } diff --git a/application/application_interface_query.cpp b/application/application_interface_query.cpp new file mode 100644 index 000000000..19a85a1e1 --- /dev/null +++ b/application/application_interface_query.cpp @@ -0,0 +1,2 @@ +#include "application_glue.hpp" +GRANITE_APPLICATION_DECL_DEFAULT_QUERY() \ No newline at end of file diff --git a/application/platforms/application_android.cpp b/application/platforms/application_android.cpp index b8d214aaf..21f367ebd 100644 --- a/application/platforms/application_android.cpp +++ b/application/platforms/application_android.cpp @@ -1071,7 +1071,10 @@ void android_main(android_app *app) global_state.app = app; init_jni(); - Global::init(); + + ApplicationQueryDefaultManagerFlags flags{Global::MANAGER_FEATURE_DEFAULT_BITS}; + query_application_interface(ApplicationQuery::DefaultManagerFlags, &flags, sizeof(flags)); + Global::init(flags.manager_feature_flags); LOGI("Starting Granite!\n"); diff --git a/application/platforms/application_glfw.cpp b/application/platforms/application_glfw.cpp index 967bc2018..033353a0b 100644 --- a/application/platforms/application_glfw.cpp +++ b/application/platforms/application_glfw.cpp @@ -659,9 +659,13 @@ static void close_cb(GLFWwindow *window) namespace Granite { -int application_main(Application *(*create_application)(int, char **), int argc, char *argv[]) +int application_main( + bool (*query_application_interface)(ApplicationQuery, void *, size_t), + Application *(*create_application)(int, char **), int argc, char *argv[]) { - Granite::Global::init(); + ApplicationQueryDefaultManagerFlags flags{Global::MANAGER_FEATURE_DEFAULT_BITS}; + query_application_interface(ApplicationQuery::DefaultManagerFlags, &flags, sizeof(flags)); + Granite::Global::init(flags.manager_feature_flags); Granite::WSIPlatformGLFW::Options options; int exit_code; diff --git a/application/platforms/application_headless.cpp b/application/platforms/application_headless.cpp index 3f8add9be..cbe7a4a73 100644 --- a/application/platforms/application_headless.cpp +++ b/application/platforms/application_headless.cpp @@ -479,7 +479,10 @@ static void print_help() namespace Granite { -int application_main_headless(Application *(*create_application)(int, char **), int argc, char *argv[]) +int application_main_headless( + bool (*query_application_interface)(ApplicationQuery, void *, size_t), + Application *(*create_application)(int, char **), + int argc, char *argv[]) { if (argc < 1) return 1; @@ -522,14 +525,19 @@ int application_main_headless(Application *(*create_application)(int, char **), if (!Util::parse_cli_filtered(std::move(cbs), argc, argv, exit_code)) return exit_code; - Granite::Global::init(Granite::Global::MANAGER_FEATURE_DEFAULT_BITS); + ApplicationQueryDefaultManagerFlags flags{Global::MANAGER_FEATURE_DEFAULT_BITS}; + query_application_interface(ApplicationQuery::DefaultManagerFlags, &flags, sizeof(flags)); + Granite::Global::init(flags.manager_feature_flags); - if (!args.assets.empty()) - GRANITE_FILESYSTEM()->register_protocol("assets", std::make_unique(args.assets)); - if (!args.builtin.empty()) - GRANITE_FILESYSTEM()->register_protocol("builtin", std::make_unique(args.builtin)); - if (!args.cache.empty()) - GRANITE_FILESYSTEM()->register_protocol("cache", std::make_unique(args.cache)); + if (flags.manager_feature_flags & Global::MANAGER_FEATURE_FILESYSTEM_BIT) + { + if (!args.assets.empty()) + GRANITE_FILESYSTEM()->register_protocol("assets", std::make_unique(args.assets)); + if (!args.builtin.empty()) + GRANITE_FILESYSTEM()->register_protocol("builtin", std::make_unique(args.builtin)); + if (!args.cache.empty()) + GRANITE_FILESYSTEM()->register_protocol("cache", std::make_unique(args.cache)); + } auto app = std::unique_ptr(create_application(argc, argv)); diff --git a/application/platforms/application_khr_display.cpp b/application/platforms/application_khr_display.cpp index e5b2f94f5..c8b432c8d 100644 --- a/application/platforms/application_khr_display.cpp +++ b/application/platforms/application_khr_display.cpp @@ -358,9 +358,14 @@ static void signal_handler(int) namespace Granite { -int application_main(Application *(*create_application)(int, char **), int argc, char *argv[]) +int application_main( + bool (*query_application_interface)(ApplicationQuery, void *, size_t), + Application *(*create_application)(int, char **), int argc, char *argv[]) { - Global::init(); + ApplicationQueryDefaultManagerFlags flags{Global::MANAGER_FEATURE_DEFAULT_BITS}; + query_application_interface(ApplicationQuery::DefaultManagerFlags, &flags, sizeof(flags)); + Global::init(flags.manager_feature_flags); + auto app = std::unique_ptr(create_application(argc, argv)); if (app) { diff --git a/application/platforms/application_libretro.cpp b/application/platforms/application_libretro.cpp index 80b7a693c..ea7c107ed 100644 --- a/application/platforms/application_libretro.cpp +++ b/application/platforms/application_libretro.cpp @@ -132,7 +132,9 @@ static retro_hw_render_callback hw_render; RETRO_API void retro_init(void) { - Global::init(); + ApplicationQueryDefaultManagerFlags flags{Global::MANAGER_FEATURE_DEFAULT_BITS}; + query_application_interface(ApplicationQuery::DefaultManagerFlags, &flags, sizeof(flags)); + Global::init(flags.manager_feature_flags); } RETRO_API void retro_deinit(void)