From 75e6db45f108dbe8819f705b2457f209812b7234 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Mon, 7 Mar 2022 00:05:40 +0300 Subject: [PATCH] Redesign resources system: centralized id-based resource registry --- libs/gfx/source/painter.cpp | 2 +- libs/rs/CMakeLists.txt | 6 ++ libs/rs/include/psemek/rs/registry.hpp | 40 ++++++++ libs/rs/include/psemek/rs/resource.hpp | 18 ++++ libs/rs/source/registry.cpp | 106 +++++++++++++++++++++ libs/ui/source/default_element_factory.cpp | 2 +- libs/ui/source/default_fonts.cpp | 6 +- tools/resource/CMakeLists.txt | 2 + tools/resource/compiler.cpp | 11 ++- 9 files changed, 183 insertions(+), 10 deletions(-) create mode 100644 libs/rs/CMakeLists.txt create mode 100644 libs/rs/include/psemek/rs/registry.hpp create mode 100644 libs/rs/include/psemek/rs/resource.hpp create mode 100644 libs/rs/source/registry.cpp diff --git a/libs/gfx/source/painter.cpp b/libs/gfx/source/painter.cpp index d13f7e94..ccc6c16d 100644 --- a/libs/gfx/source/painter.cpp +++ b/libs/gfx/source/painter.cpp @@ -164,7 +164,7 @@ namespace psemek::gfx text_mesh.setup, gfx::normalized, geom::point>(); texture_mesh.setup, gfx::normalized>>(); - font_texture.load(gfx::read_png_monochrome(io::memory_istream{resource::font_9x12_png})); + font_texture.load(gfx::read_png_monochrome(io::memory_istream{resource::font_9x12_png.data})); font_texture.bind(); gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_SWIZZLE_G, gl::RED); diff --git a/libs/rs/CMakeLists.txt b/libs/rs/CMakeLists.txt new file mode 100644 index 00000000..f8af3c6e --- /dev/null +++ b/libs/rs/CMakeLists.txt @@ -0,0 +1,6 @@ +file(GLOB_RECURSE PSEMEK_IO_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp") +file(GLOB_RECURSE PSEMEK_IO_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "source/*.cpp") + +psemek_add_library(psemek-rs ${PSEMEK_IO_HEADERS} ${PSEMEK_IO_SOURCES}) +target_include_directories(psemek-rs PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(psemek-rs PRIVATE psemek-util) diff --git a/libs/rs/include/psemek/rs/registry.hpp b/libs/rs/include/psemek/rs/registry.hpp new file mode 100644 index 00000000..fb43390e --- /dev/null +++ b/libs/rs/include/psemek/rs/registry.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include + +#include + +namespace psemek::rs +{ + + struct unknown_id_error + : std::runtime_error + { + unknown_id_error(rs::id id); + + rs::id id() const { return id_; } + + private: + rs::id id_; + }; + + struct unknown_name_error + : std::runtime_error + { + unknown_name_error(std::string_view name); + + std::string_view name() const { return name_; } + + private: + std::string_view name_; + }; + + resource const * find(id id); + resource const * find(std::string_view name); + + resource const & get(id id); + resource const & get(std::string_view name); + + id add(std::string_view name, std::string_view data); + +} diff --git a/libs/rs/include/psemek/rs/resource.hpp b/libs/rs/include/psemek/rs/resource.hpp new file mode 100644 index 00000000..5a027059 --- /dev/null +++ b/libs/rs/include/psemek/rs/resource.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +namespace psemek::rs +{ + + using id = std::uint32_t; + + struct resource + { + rs::id id; + std::string_view name; + std::string_view data; + }; + +} diff --git a/libs/rs/source/registry.cpp b/libs/rs/source/registry.cpp new file mode 100644 index 00000000..ab67b4d9 --- /dev/null +++ b/libs/rs/source/registry.cpp @@ -0,0 +1,106 @@ +#include + +#include + +#include +#include +#include +#include +#include + +namespace psemek::rs +{ + + namespace + { + + auto & resources_mutex() + { + static std::mutex instance; + return instance; + } + + auto & resources() + { + static std::map instance; + return instance; + } + + auto & name_map_mutex() + { + static std::mutex instance; + return instance; + } + + auto & name_map() + { + static std::unordered_map instance; + return instance; + } + + std::atomic next_id{0}; + + } + + unknown_id_error::unknown_id_error(rs::id id) + : std::runtime_error(util::to_string("unknown resource id: ", id)) + , id_(id) + {} + + unknown_name_error::unknown_name_error(std::string_view name) + : std::runtime_error(util::to_string("unknown resource name: ", name)) + {} + + resource const * find(id id) + { + std::lock_guard lock{resources_mutex()}; + auto it = resources().find(id); + if (it == resources().end()) + return nullptr; + return &(it->second); + } + + resource const * find(std::string_view name) + { + rs::id id; + { + std::lock_guard lock{name_map_mutex()}; + auto it = name_map().find(name); + if (it == name_map().end()) + return nullptr; + id = it->second; + } + return find(id); + } + + resource const & get(id id) + { + auto result = find(id); + if (!result) + throw unknown_id_error{id}; + return *result; + } + + resource const & get(std::string_view name) + { + auto result = find(name); + if (!result) + throw unknown_name_error{name}; + return *result; + } + + id add(std::string_view name, std::string_view data) + { + auto id = next_id.fetch_add(1); + { + std::lock_guard lock{name_map_mutex()}; + name_map()[name] = id; + } + { + std::lock_guard lock{resources_mutex()}; + resources()[id] = {id, name, data}; + } + return id; + } + +} diff --git a/libs/ui/source/default_element_factory.cpp b/libs/ui/source/default_element_factory.cpp index b6eee86f..7ad1b961 100644 --- a/libs/ui/source/default_element_factory.cpp +++ b/libs/ui/source/default_element_factory.cpp @@ -718,7 +718,7 @@ namespace psemek::ui default_element_factory::impl::impl() { - cross_red_16x16 = std::make_shared(gfx::texture_2d::from_pixmap(gfx::read_png(io::memory_istream{resources::cross_red_16x16_png}))); + cross_red_16x16 = std::make_shared(gfx::texture_2d::from_pixmap(gfx::read_png(io::memory_istream{resources::cross_red_16x16_png.data}))); cross_red_16x16->nearest_filter(); } diff --git a/libs/ui/source/default_fonts.cpp b/libs/ui/source/default_fonts.cpp index b779ab28..55e5087e 100644 --- a/libs/ui/source/default_fonts.cpp +++ b/libs/ui/source/default_fonts.cpp @@ -18,7 +18,7 @@ namespace psemek::ui std::string_view name = "default_monospace_9x12"; geom::vector size{9, 12}; - gfx::texture_2d atlas = gfx::texture_2d::from_pixmap(gfx::read_png_monochrome(io::memory_istream{gfx::resource::font_9x12_png})); + gfx::texture_2d atlas = gfx::texture_2d::from_pixmap(gfx::read_png_monochrome(io::memory_istream{gfx::resource::font_9x12_png.data})); atlas.nearest_filter(); atlas.clamp(); gl::TexParameteri(atlas.target, gl::TEXTURE_SWIZZLE_G, gl::RED); @@ -49,7 +49,7 @@ namespace psemek::ui std::string_view name = "default_9x12"; geom::vector size{9, 12}; - gfx::texture_2d atlas = gfx::texture_2d::from_pixmap(gfx::read_png_monochrome(io::memory_istream{gfx::resource::font_9x12_png})); + gfx::texture_2d atlas = gfx::texture_2d::from_pixmap(gfx::read_png_monochrome(io::memory_istream{gfx::resource::font_9x12_png.data})); atlas.nearest_filter(); atlas.clamp(); gl::TexParameteri(atlas.target, gl::TEXTURE_SWIZZLE_G, gl::RED); @@ -58,7 +58,7 @@ namespace psemek::ui std::unordered_map glyphs; { - std::istringstream is{std::string(ui::resources::font_9x12_glyphs_txt)}; + std::istringstream is{std::string(ui::resources::font_9x12_glyphs_txt.data)}; std::string line; while (std::getline(is, line)) diff --git a/tools/resource/CMakeLists.txt b/tools/resource/CMakeLists.txt index 1b1aee00..b2ac3d84 100644 --- a/tools/resource/CMakeLists.txt +++ b/tools/resource/CMakeLists.txt @@ -7,6 +7,8 @@ function(psemek_add_resources_impl MODE TARGET) endif() endif() + target_link_libraries(${TARGET} ${MODE} psemek-rs) + get_target_property(OUT_DIR ${TARGET} BINARY_DIR) get_target_property(INPUT_DIR ${TARGET} SOURCE_DIR) diff --git a/tools/resource/compiler.cpp b/tools/resource/compiler.cpp index 7fed9f46..eac81cb0 100644 --- a/tools/resource/compiler.cpp +++ b/tools/resource/compiler.cpp @@ -13,7 +13,8 @@ int main(int argc, char * argv[]) return EXIT_FAILURE; } - std::string name = argv[2]; + std::string fullname = argv[2]; + std::string name = fullname; std::string ns; std::size_t const last_slash = name.find_last_of('/'); @@ -43,7 +44,7 @@ int main(int argc, char * argv[]) output_header << "#pragma once\n" << "\n" - << "#include \n" + << "#include \n" << "\n"; if (!ns.empty()) output_header @@ -51,7 +52,7 @@ int main(int argc, char * argv[]) << "{\n" << "\n"; - output_header << tab << "extern std::string_view " << name << ";\n"; + output_header << tab << "extern ::psemek::rs::resource const & " << name << ";\n"; if (!ns.empty()) output_header << "\n" @@ -62,7 +63,7 @@ int main(int argc, char * argv[]) std::ofstream output_source{argv[4]}; output_source - << "#include \n" + << "#include \n" << "\n"; output_source << "alignas(16) static const char data[" << input_data.size() << "] = {\n"; @@ -94,7 +95,7 @@ int main(int argc, char * argv[]) << "{\n" << "\n"; - output_source << tab << "std::string_view " << name << "{data, sizeof(data)};\n"; + output_source << tab << "::psemek::rs::resource const & " << name << " = ::psemek::rs::get(::psemek::rs::add(\"" << fullname << "\", {data, sizeof(data)}));\n"; if (!ns.empty()) output_source << "\n"