Skip to content

Commit 7aaf536

Browse files
authored
feat: Create References<T>::adoptRef and References<T>::adoptEngineRef (#10)
Creates two helper functions in `References.h`: - `References<T>::adoptRef(...)`: Adopt a raw reference to `T` and take over it's memory ownership. When the resulting `shared_ptr<T>` is deleted, `cleanup` will be called with the reference to `T`, and the caller is expected to properly clean up `T`. - `References<T>::adoptEngineRef(...)`: Same as `adoptRef(...)`, but with an additional argument: `Engine`. This is used to clean up children of `Engine`, e.g. via `Engine::destroy(Renderer)`. Usage: ```cpp // 1. Adopt any reference to a shared_ptr with a custom deleter function (in this case, Engine*) std::shared_ptr<Engine> _engine = References<Engine>::adoptRef(Engine::create(backend), [](Engine* engine) { engine->destroy(&engine); }); // 2. Adopt a filament::Engine-specific object to a shared_ptr with a custom deleter function that needs the `Engine` to perform cleanup: std::shared_ptr<Renderer> renderer = References<Renderer>::adoptEngineRef(_engine, _engine->createRenderer(), [](const std::shared_ptr<Engine>& engine, Renderer* renderer) { engine->destroy(renderer); }); ```
1 parent 6477edc commit 7aaf536

File tree

3 files changed

+56
-19
lines changed

3 files changed

+56
-19
lines changed

package/cpp/References.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//
2+
// Created by Marc Rousavy on 23.02.24.
3+
//
4+
5+
#pragma once
6+
7+
#include <filament/Engine.h>
8+
#include <functional>
9+
#include <memory>
10+
11+
namespace margelo {
12+
13+
template <typename T> struct References {
14+
public:
15+
using CleanupRefFunction = std::function<void(T* ref)>;
16+
using CleanupEngineRefFunction = std::function<void(std::shared_ptr<filament::Engine> engine, T* ref)>;
17+
18+
struct Deleter {
19+
public:
20+
explicit Deleter(const CleanupRefFunction& cleanup) : _cleanup(std::move(cleanup)) {}
21+
void operator()(T* ref) {
22+
_cleanup(ref);
23+
}
24+
25+
private:
26+
CleanupRefFunction _cleanup;
27+
};
28+
29+
/**
30+
* Adopt a raw reference to T and take over it's memory ownership.
31+
* When the resulting `shared_ptr` is deleted, `cleanup` will be called with the reference to T, and the caller is expected to properly
32+
* clean up T.
33+
* @param value The raw reference to T that will be adopted.
34+
* @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
35+
* here.
36+
* @return A shared_ptr safely managing the reference to T.
37+
*/
38+
static std::shared_ptr<T> adoptRef(T* value, const CleanupRefFunction& cleanup) {
39+
return std::shared_ptr<T>(value, Deleter(std::move(cleanup)));
40+
}
41+
42+
/**
43+
* Same as `adoptRef(T*, CleanupRefFunction)`, but with an additional argument: `Engine`.
44+
* This is used to clean up children of `Engine`, e.g. via `Engine::destroy(Renderer)`.
45+
*/
46+
static std::shared_ptr<T> adoptEngineRef(const std::shared_ptr<filament::Engine>& engine, T* value, CleanupEngineRefFunction cleanup) {
47+
return adoptRef(value, [engine = std::move(engine), cleanup = std::move(cleanup)](T* ref) { cleanup(engine, ref); });
48+
}
49+
};
50+
51+
} // namespace margelo

package/cpp/core/EngineWrapper.cpp

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,14 @@
44

55
#include "EngineWrapper.h"
66

7+
#include "References.h"
78
#include <filament/Engine.h>
89
#include <filament/SwapChain.h>
910

1011
namespace margelo {
1112

1213
EngineWrapper::EngineWrapper(filament::Engine::Backend backend) {
13-
_engine = Engine::create(backend);
14-
}
15-
16-
EngineWrapper::~EngineWrapper() {
17-
if (_swapChain) {
18-
_engine->destroy(_swapChain);
19-
}
20-
_engine->destroy(&_engine);
14+
_engine = References<Engine>::adoptRef(Engine::create(backend), [](Engine* engine) { engine->destroy(&engine); });
2115
}
2216

2317
void EngineWrapper::loadHybridMethods() {
@@ -39,17 +33,11 @@ void EngineWrapper::setSurfaceProvider(std::shared_ptr<SurfaceProvider> surfaceP
3933

4034
void EngineWrapper::setSurface(std::shared_ptr<Surface> surface) {
4135
void* nativeWindow = surface->getSurface();
42-
if (_swapChain == nullptr || _swapChain->getNativeWindow() != nativeWindow) {
43-
destroySurface();
44-
_swapChain = _engine->createSwapChain(nativeWindow);
45-
}
36+
// TODO: do something with surface
4637
}
4738

4839
void EngineWrapper::destroySurface() {
49-
if (_swapChain != nullptr) {
50-
_engine->destroy(_swapChain);
51-
_swapChain = nullptr;
52-
}
40+
// TODO: destroy surface
5341
}
5442

5543
} // namespace margelo

package/cpp/core/EngineWrapper.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ using namespace filament;
1818
class EngineWrapper : public HybridObject {
1919
public:
2020
explicit EngineWrapper(filament::Engine::Backend backend);
21-
~EngineWrapper();
2221

2322
void setSurfaceProvider(std::shared_ptr<SurfaceProvider> surfaceProvider);
2423

@@ -29,8 +28,7 @@ class EngineWrapper : public HybridObject {
2928
void destroySurface();
3029

3130
private:
32-
Engine* _engine;
33-
SwapChain* _swapChain;
31+
std::shared_ptr<Engine> _engine;
3432
std::shared_ptr<SurfaceProvider> _surfaceProvider;
3533
std::unique_ptr<Listener> _listener;
3634
};

0 commit comments

Comments
 (0)