Skip to content

Commit

Permalink
feat: Create References<T>::adoptRef and `References<T>::adoptEngin…
Browse files Browse the repository at this point in the history
…eRef` (#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);
});
```
  • Loading branch information
mrousavy authored Feb 23, 2024
1 parent 6477edc commit 7aaf536
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 19 deletions.
51 changes: 51 additions & 0 deletions package/cpp/References.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// Created by Marc Rousavy on 23.02.24.
//

#pragma once

#include <filament/Engine.h>
#include <functional>
#include <memory>

namespace margelo {

template <typename T> struct References {
public:
using CleanupRefFunction = std::function<void(T* ref)>;
using CleanupEngineRefFunction = std::function<void(std::shared_ptr<filament::Engine> 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<T> adoptRef(T* value, const CleanupRefFunction& cleanup) {
return std::shared_ptr<T>(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<T> adoptEngineRef(const std::shared_ptr<filament::Engine>& engine, T* value, CleanupEngineRefFunction cleanup) {
return adoptRef(value, [engine = std::move(engine), cleanup = std::move(cleanup)](T* ref) { cleanup(engine, ref); });
}
};

} // namespace margelo
20 changes: 4 additions & 16 deletions package/cpp/core/EngineWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,14 @@

#include "EngineWrapper.h"

#include "References.h"
#include <filament/Engine.h>
#include <filament/SwapChain.h>

namespace margelo {

EngineWrapper::EngineWrapper(filament::Engine::Backend backend) {
_engine = Engine::create(backend);
}

EngineWrapper::~EngineWrapper() {
if (_swapChain) {
_engine->destroy(_swapChain);
}
_engine->destroy(&_engine);
_engine = References<Engine>::adoptRef(Engine::create(backend), [](Engine* engine) { engine->destroy(&engine); });
}

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

void EngineWrapper::setSurface(std::shared_ptr<Surface> 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
4 changes: 1 addition & 3 deletions package/cpp/core/EngineWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -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> surfaceProvider);

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

private:
Engine* _engine;
SwapChain* _swapChain;
std::shared_ptr<Engine> _engine;
std::shared_ptr<SurfaceProvider> _surfaceProvider;
std::unique_ptr<Listener> _listener;
};
Expand Down

0 comments on commit 7aaf536

Please sign in to comment.