Compare commits
9 commits
155ced8410
...
664b1d613e
| Author | SHA1 | Date | |
|---|---|---|---|
| 664b1d613e | |||
| ae3b91e7b1 | |||
| 32bbc93eea | |||
| 6ea10520b5 | |||
| 55d18aaa33 | |||
| 8587ba6bc0 | |||
| f30da1a2ad | |||
| 75471c6054 | |||
| 1195bd26d5 |
14 changed files with 210 additions and 38 deletions
18
libs/app/include/psemek/app/storage.hpp
Normal file
18
libs/app/include/psemek/app/storage.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include <psemek/io/stream.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
|
||||
namespace psemek::app
|
||||
{
|
||||
|
||||
std::filesystem::path storage_root();
|
||||
void set_storage_root(std::filesystem::path const & root);
|
||||
|
||||
// Implemented by a backend library
|
||||
std::unique_ptr<io::istream> read_storage(std::filesystem::path const & relative_path);
|
||||
std::unique_ptr<io::ostream> write_storage(std::filesystem::path const & relative_path);
|
||||
|
||||
}
|
||||
24
libs/app/source/storage.cpp
Normal file
24
libs/app/source/storage.cpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#include <psemek/app/storage.hpp>
|
||||
#include <psemek/util/executable_path.hpp>
|
||||
|
||||
namespace psemek::app
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
static std::filesystem::path global_storage_root = util::executable_path().parent_path();
|
||||
|
||||
}
|
||||
|
||||
std::filesystem::path storage_root()
|
||||
{
|
||||
return global_storage_root;
|
||||
}
|
||||
|
||||
void set_storage_root(std::filesystem::path const & root)
|
||||
{
|
||||
global_storage_root = root;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -4,19 +4,40 @@
|
|||
|
||||
#include <filesystem>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
|
||||
namespace psemek::io
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
struct buffer_hook
|
||||
{
|
||||
static constexpr std::size_t buffer_size = 1 << 20; // 1 MB
|
||||
std::unique_ptr<char[]> buffer{new char[buffer_size]};
|
||||
|
||||
void apply(FILE * file)
|
||||
{
|
||||
std::setvbuf(file, buffer.get(), _IOFBF, buffer_size);
|
||||
}
|
||||
};
|
||||
#else
|
||||
struct buffer_hook
|
||||
{
|
||||
void apply(FILE *) {}
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
struct file_istream
|
||||
: istream
|
||||
{
|
||||
file_istream() = default;
|
||||
|
||||
file_istream(FILE * file)
|
||||
: file_{file}
|
||||
{}
|
||||
|
||||
file_istream(FILE * file);
|
||||
file_istream(std::filesystem::path const & path);
|
||||
|
||||
file_istream(file_istream && s)
|
||||
|
|
@ -49,6 +70,7 @@ namespace psemek::io
|
|||
|
||||
private:
|
||||
FILE * file_ = nullptr;
|
||||
[[no_unique_address]] detail::buffer_hook buffer_hook_;
|
||||
};
|
||||
|
||||
struct file_ostream
|
||||
|
|
@ -58,10 +80,7 @@ namespace psemek::io
|
|||
|
||||
file_ostream() = default;
|
||||
|
||||
file_ostream(FILE * file)
|
||||
: file_{file}
|
||||
{}
|
||||
|
||||
file_ostream(FILE * file);
|
||||
file_ostream(std::filesystem::path const & path, unsigned flags = 0);
|
||||
|
||||
file_ostream(file_ostream && s)
|
||||
|
|
@ -94,6 +113,7 @@ namespace psemek::io
|
|||
|
||||
private:
|
||||
FILE * file_ = nullptr;
|
||||
[[no_unique_address]] detail::buffer_hook buffer_hook_;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <psemek/io/stream.hpp>
|
||||
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace psemek::io
|
||||
{
|
||||
|
|
@ -131,4 +132,55 @@ namespace psemek::io
|
|||
char * end_ = nullptr;
|
||||
};
|
||||
|
||||
struct expanding_memory_ostream
|
||||
: ostream
|
||||
{
|
||||
expanding_memory_ostream() = default;
|
||||
|
||||
expanding_memory_ostream(std::vector<char> & storage)
|
||||
: buffer_(&storage)
|
||||
{}
|
||||
|
||||
expanding_memory_ostream(expanding_memory_ostream && s)
|
||||
: storage_(std::move(s.storage_))
|
||||
, buffer_(s.buffer_)
|
||||
{
|
||||
s.reset();
|
||||
}
|
||||
|
||||
expanding_memory_ostream & operator = (expanding_memory_ostream && s)
|
||||
{
|
||||
if (this != &s)
|
||||
{
|
||||
storage_ = std::move(s.storage_);
|
||||
buffer_ = s.buffer_;
|
||||
s.reset();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
storage_.clear();
|
||||
buffer_ = &storage_;
|
||||
}
|
||||
|
||||
void swap(expanding_memory_ostream & s)
|
||||
{
|
||||
std::swap(storage_, s.storage_);
|
||||
std::swap(buffer_, s.buffer_);
|
||||
}
|
||||
|
||||
char * data() const { return buffer_->data(); }
|
||||
|
||||
std::vector<char> & buffer() { return *buffer_; }
|
||||
|
||||
std::size_t write(char const * p, std::size_t size) override;
|
||||
|
||||
private:
|
||||
std::vector<char> storage_;
|
||||
std::vector<char> * buffer_ = &storage_;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,11 @@ namespace psemek::io
|
|||
#else
|
||||
char const * fopen_read_mode()
|
||||
{
|
||||
#ifdef __EMSCRIPTEN__
|
||||
return "r+b";
|
||||
#else
|
||||
return "rb";
|
||||
#endif
|
||||
}
|
||||
|
||||
char const * fopen_write_mode(unsigned flags)
|
||||
|
|
@ -65,9 +69,17 @@ namespace psemek::io
|
|||
|
||||
}
|
||||
|
||||
file_istream::file_istream(FILE * file)
|
||||
: file_{file}
|
||||
{
|
||||
buffer_hook_.apply(file_);
|
||||
}
|
||||
|
||||
file_istream::file_istream(std::filesystem::path const & path)
|
||||
: file_{safe_fopen(path, fopen_read_mode())}
|
||||
{}
|
||||
{
|
||||
buffer_hook_.apply(file_);
|
||||
}
|
||||
|
||||
void file_istream::reset()
|
||||
{
|
||||
|
|
@ -88,9 +100,17 @@ namespace psemek::io
|
|||
return std::feof(file_) != 0;
|
||||
}
|
||||
|
||||
file_ostream::file_ostream(FILE * file)
|
||||
: file_{file}
|
||||
{
|
||||
buffer_hook_.apply(file_);
|
||||
}
|
||||
|
||||
file_ostream::file_ostream(std::filesystem::path const & path, unsigned flags)
|
||||
: file_{safe_fopen(path, fopen_write_mode(flags))}
|
||||
{}
|
||||
{
|
||||
buffer_hook_.apply(file_);
|
||||
}
|
||||
|
||||
void file_ostream::reset()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,4 +23,10 @@ namespace psemek::io
|
|||
return size;
|
||||
}
|
||||
|
||||
std::size_t expanding_memory_ostream::write(char const * p, std::size_t size)
|
||||
{
|
||||
buffer_->insert(buffer_->end(), p, p + size);
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ namespace psemek::log
|
|||
#if __APPLE__
|
||||
::pthread_setname_np(name.data());
|
||||
#else
|
||||
#if !(defined __EMSCRIPTEN__) || (defined __EMSCRIPTEN_PTHREADS__)
|
||||
#if !(defined __EMSCRIPTEN__)
|
||||
::pthread_setname_np(::pthread_self(), name.data());
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# On web SDL is provided by emsdk itself
|
||||
if(NOT CMAKE_SYSTEM_NAME STREQUAL Emscripten)
|
||||
if(NOT PSEMEK_PLATFORM_WEB)
|
||||
find_package(SDL2 REQUIRED)
|
||||
endif()
|
||||
|
||||
|
|
@ -14,7 +14,11 @@ endif()
|
|||
|
||||
psemek_add_library(psemek-sdl2 ${PSEMEK_SDL2_HEADERS} ${PSEMEK_SDL2_SOURCES} ${PSEMEK_SDL2_PLATFORM_SOURCES})
|
||||
target_include_directories(psemek-sdl2 PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
target_link_libraries(psemek-sdl2 PUBLIC psemek-log psemek-util psemek-audio psemek-app SDL2)
|
||||
target_link_libraries(psemek-sdl2 PUBLIC psemek-log psemek-util psemek-audio psemek-app)
|
||||
if(NOT PSEMEK_PLATFORM_WEB)
|
||||
target_link_libraries(psemek-sdl2 PUBLIC SDL2)
|
||||
endif()
|
||||
|
||||
if(PSEMEK_GRAPHICS_API STREQUAL OPENGL)
|
||||
target_link_libraries(psemek-sdl2 PUBLIC psemek-gfx)
|
||||
elseif(PSEMEK_GRAPHICS_API STREQUAL WEBGPU)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <psemek/app/application.hpp>
|
||||
#include <psemek/app/resource.hpp>
|
||||
#include <psemek/app/storage.hpp>
|
||||
#include <psemek/gfx/init.hpp>
|
||||
#include <psemek/sdl2/init.hpp>
|
||||
#include <psemek/sdl2/window.hpp>
|
||||
|
|
@ -16,6 +17,7 @@
|
|||
#include <emscripten/emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/wasmfs.h>
|
||||
|
||||
struct em_state
|
||||
{
|
||||
|
|
@ -52,9 +54,13 @@ int main(int argc, char ** argv) try
|
|||
log::register_thread("main");
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
// In web builds, resources are in the root of
|
||||
// In web builds, resources are stored in
|
||||
// the Emscripten virtual filesystem
|
||||
app::set_resource_root("/");
|
||||
app::set_resource_root("/resources");
|
||||
|
||||
backend_t opfs = wasmfs_create_opfs_backend();
|
||||
wasmfs_create_directory("/storage", 0777, opfs);
|
||||
app::set_storage_root("/storage");
|
||||
#endif
|
||||
|
||||
auto const factory = app::make_application_factory();
|
||||
|
|
@ -111,19 +117,17 @@ int main(int argc, char ** argv) try
|
|||
SDL_StopTextInput();
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
emscripten_request_animation_frame_loop([](double, void*) -> EM_BOOL {
|
||||
emscripten_set_main_loop([]{
|
||||
if (sdl2::poll_events(*em_state.application))
|
||||
em_state.application->stop();
|
||||
|
||||
if (!em_state.application->running())
|
||||
return EM_FALSE;
|
||||
emscripten_cancel_main_loop();
|
||||
|
||||
em_state.application->update();
|
||||
em_state.application->present();
|
||||
em_state.window->swap();
|
||||
|
||||
return EM_TRUE;
|
||||
}, nullptr);
|
||||
}, 0, 1);
|
||||
#else
|
||||
while (application->running())
|
||||
{
|
||||
|
|
@ -134,9 +138,10 @@ int main(int argc, char ** argv) try
|
|||
application->present();
|
||||
window.swap();
|
||||
}
|
||||
#endif
|
||||
|
||||
log::info() << "Quitting";
|
||||
#endif
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch (psemek::util::exception const & e)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace psemek::app
|
|||
|
||||
std::unique_ptr<io::istream> open_resource(std::filesystem::path const & relative_path)
|
||||
{
|
||||
log::info() << "Opening resource " << relative_path;
|
||||
log::debug() << "Opening resource " << relative_path;
|
||||
return std::make_unique<io::file_istream>(app::resource_root() / relative_path);
|
||||
}
|
||||
|
||||
|
|
|
|||
20
libs/sdl2/source/storage.cpp
Normal file
20
libs/sdl2/source/storage.cpp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#include <psemek/app/storage.hpp>
|
||||
#include <psemek/io/file_stream.hpp>
|
||||
#include <psemek/log/log.hpp>
|
||||
|
||||
namespace psemek::app
|
||||
{
|
||||
|
||||
std::unique_ptr<io::istream> read_storage(std::filesystem::path const & relative_path)
|
||||
{
|
||||
log::debug() << "Reading storage " << relative_path;
|
||||
return std::make_unique<io::file_istream>(app::storage_root() / relative_path);
|
||||
}
|
||||
|
||||
std::unique_ptr<io::ostream> write_storage(std::filesystem::path const & relative_path)
|
||||
{
|
||||
log::debug() << "Writing storage " << relative_path;
|
||||
return std::make_unique<io::file_ostream>(app::storage_root() / relative_path);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ if(PSEMEK_PACKAGE_MODE)
|
|||
set(PSEMEK_PACKAGE_LINK_FLAGS_RAW)
|
||||
|
||||
if(PSEMEK_PLATFORM_WEB)
|
||||
list(APPEND PSEMEK_PACKAGE_LINK_FLAGS_RAW "-sMIN_WEBGL_VERSION=2" "-sNO_DISABLE_EXCEPTION_CATCHING" "-sFULL_ES3")
|
||||
list(APPEND PSEMEK_PACKAGE_LINK_FLAGS_RAW -sUSE_SDL=2 -sMIN_WEBGL_VERSION=2 -sNO_DISABLE_EXCEPTION_CATCHING -sFULL_ES3 -sWASMFS -sALLOW_MEMORY_GROWTH -sGROWABLE_ARRAYBUFFERS=0 -sASYNCIFY)
|
||||
list(APPEND PSEMEK_PACKAGE_LINK_FLAGS_RAW "-sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='$autoResumeAudioContext','$dynCall'")
|
||||
if(CMAKE_BUILD_TYPE STREQUAL Debug)
|
||||
list(APPEND PSEMEK_PACKAGE_LINK_FLAGS_RAW "-g")
|
||||
|
|
@ -218,7 +218,7 @@ function(psemek_package_files target)
|
|||
elseif(PSEMEK_PLATFORM_WEB)
|
||||
foreach(_FILE IN LISTS ARGN)
|
||||
target_link_options(${target} PRIVATE
|
||||
"--preload-file=${CMAKE_CURRENT_LIST_DIR}/${_FILE}@/${_FILE}"
|
||||
"--preload-file=${CMAKE_CURRENT_LIST_DIR}/${_FILE}@/resources/${_FILE}"
|
||||
)
|
||||
endforeach()
|
||||
else()
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ FROM lisyarus/psemek:package-linux
|
|||
|
||||
# Install emsdk - the version the build was tested at
|
||||
WORKDIR /home
|
||||
RUN git clone --branch 3.1.46 https://github.com/emscripten-core/emsdk.git
|
||||
RUN git clone --branch 6.0.2 https://github.com/emscripten-core/emsdk.git
|
||||
WORKDIR /home/emsdk
|
||||
RUN ./emsdk install 3.1.46
|
||||
RUN ./emsdk activate 3.1.46
|
||||
RUN ./emsdk install 6.0.2
|
||||
RUN ./emsdk activate 6.0.2
|
||||
RUN . ./emsdk_env.sh && embuilder build sdl2 sdl2-mt
|
||||
|
||||
WORKDIR /home
|
||||
COPY env-helper.sh .
|
||||
# Source emsdk env variables when running the container
|
||||
|
|
@ -13,6 +15,7 @@ ENTRYPOINT ["/home/env-helper.sh"]
|
|||
|
||||
# Install Boost sources
|
||||
WORKDIR /home
|
||||
RUN git config --global advice.detachedHead false
|
||||
RUN git clone --recurse-submodules --branch boost-1.87.0 https://github.com/boostorg/boost.git
|
||||
|
||||
# Install toolchain file & main packaging script
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ rm -rf ./*
|
|||
# right toolchain.
|
||||
emcmake cmake \
|
||||
-DBOOST_SOURCE_ROOT=$(realpath ../source)/psemek/3rdparty/boost \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DPSEMEK_PACKAGE_MODE=ON \
|
||||
-DPSEMEK_PACKAGE_HOST=OFF \
|
||||
-DPSEMEK_PACKAGE_TARGET=ON \
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue