diff --git a/package/cpp/References.h b/package/cpp/References.h new file mode 100644 index 00000000..e395a284 --- /dev/null +++ b/package/cpp/References.h @@ -0,0 +1,51 @@ +// +// Created by Marc Rousavy on 23.02.24. +// + +#pragma once + +#include +#include +#include + +namespace margelo { + +template struct References { +public: + using CleanupRefFunction = std::function; + using CleanupEngineRefFunction = std::function engine, T* ref)>; + + struct Deleter { + public: + explicit Deleter(const CleanupRefFunction& cleanup) : _cleanup(std::move(cleanup)) {} + void operator()(T* ref) { + _cleanup(ref); + } + + private: + CleanupRefFunction _cleanup; + }; + + /** + * Adopt a raw reference to T and take over it's memory ownership. + * When the resulting `shared_ptr` is deleted, `cleanup` will be called with the reference to T, and the caller is expected to properly + * clean up T. + * @param value The raw reference to T that will be adopted. + * @param cleanup The function to run when the shared_ptr's ref count reaches zero. The caller is expected to delete the reference to T + * here. + * @return A shared_ptr safely managing the reference to T. + */ + static std::shared_ptr adoptRef(T* value, const CleanupRefFunction& cleanup) { + return std::shared_ptr(value, Deleter(std::move(cleanup))); + } + + /** + * Same as `adoptRef(T*, CleanupRefFunction)`, but with an additional argument: `Engine`. + * This is used to clean up children of `Engine`, e.g. via `Engine::destroy(Renderer)`. + */ + static std::shared_ptr adoptEngineRef(const std::shared_ptr& engine, T* value, CleanupEngineRefFunction cleanup) { + return adoptRef(value, [engine = std::move(engine), cleanup = std::move(cleanup)](T* ref) { cleanup(engine, ref); }); + } +}; + +} // namespace margelo diff --git a/package/cpp/core/EngineWrapper.cpp b/package/cpp/core/EngineWrapper.cpp index 860283c8..ee193c6b 100644 --- a/package/cpp/core/EngineWrapper.cpp +++ b/package/cpp/core/EngineWrapper.cpp @@ -4,20 +4,14 @@ #include "EngineWrapper.h" +#include "References.h" #include #include namespace margelo { EngineWrapper::EngineWrapper(filament::Engine::Backend backend) { - _engine = Engine::create(backend); -} - -EngineWrapper::~EngineWrapper() { - if (_swapChain) { - _engine->destroy(_swapChain); - } - _engine->destroy(&_engine); + _engine = References::adoptRef(Engine::create(backend), [](Engine* engine) { engine->destroy(&engine); }); } void EngineWrapper::loadHybridMethods() { @@ -39,17 +33,11 @@ void EngineWrapper::setSurfaceProvider(std::shared_ptr surfaceP void EngineWrapper::setSurface(std::shared_ptr surface) { void* nativeWindow = surface->getSurface(); - if (_swapChain == nullptr || _swapChain->getNativeWindow() != nativeWindow) { - destroySurface(); - _swapChain = _engine->createSwapChain(nativeWindow); - } + // TODO: do something with surface } void EngineWrapper::destroySurface() { - if (_swapChain != nullptr) { - _engine->destroy(_swapChain); - _swapChain = nullptr; - } + // TODO: destroy surface } } // namespace margelo \ No newline at end of file diff --git a/package/cpp/core/EngineWrapper.h b/package/cpp/core/EngineWrapper.h index b251c866..d3ccecb5 100644 --- a/package/cpp/core/EngineWrapper.h +++ b/package/cpp/core/EngineWrapper.h @@ -18,7 +18,6 @@ using namespace filament; class EngineWrapper : public HybridObject { public: explicit EngineWrapper(filament::Engine::Backend backend); - ~EngineWrapper(); void setSurfaceProvider(std::shared_ptr surfaceProvider); @@ -29,8 +28,7 @@ class EngineWrapper : public HybridObject { void destroySurface(); private: - Engine* _engine; - SwapChain* _swapChain; + std::shared_ptr _engine; std::shared_ptr _surfaceProvider; std::unique_ptr _listener; };