feat: support multiple ThermionWidget on Android
This commit is contained in:
@@ -127,7 +127,16 @@ namespace thermion
|
||||
FilamentViewer::FilamentViewer(const void *sharedContext, const ResourceLoaderWrapperImpl *const resourceLoader, void *const platform, const char *uberArchivePath)
|
||||
: _resourceLoaderWrapper(resourceLoader)
|
||||
{
|
||||
|
||||
_context = (void *)sharedContext;
|
||||
|
||||
if(!_context) {
|
||||
Log("Creating, no shared context");
|
||||
} else {
|
||||
Log("Creating with shared context");
|
||||
}
|
||||
|
||||
|
||||
ASSERT_POSTCONDITION(_resourceLoaderWrapper != nullptr, "Resource loader must be non-null");
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
@@ -166,8 +175,6 @@ namespace thermion
|
||||
|
||||
createView();
|
||||
|
||||
setRenderable(_views[0], true);
|
||||
|
||||
const float aperture = _mainCamera->getAperture();
|
||||
const float shutterSpeed = _mainCamera->getShutterSpeed();
|
||||
const float sens = _mainCamera->getSensitivity();
|
||||
@@ -665,20 +672,19 @@ namespace thermion
|
||||
|
||||
Renderer *FilamentViewer::getRenderer() { return _renderer; }
|
||||
|
||||
SwapChain *FilamentViewer::createSwapChain(const void *window, uint32_t width, uint32_t height)
|
||||
SwapChain *FilamentViewer::createSwapChain(const void *window)
|
||||
{
|
||||
std::lock_guard lock(_renderMutex);
|
||||
SwapChain *swapChain = _engine->createSwapChain((void *)window, filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT | filament::backend::SWAP_CHAIN_CONFIG_READABLE | filament::SwapChain::CONFIG_HAS_STENCIL_BUFFER);
|
||||
_swapChains.push_back(swapChain);
|
||||
return swapChain;
|
||||
}
|
||||
|
||||
SwapChain *FilamentViewer::createSwapChain(uint32_t width, uint32_t height)
|
||||
{
|
||||
std::lock_guard lock(_renderMutex);
|
||||
SwapChain *swapChain;
|
||||
if (window)
|
||||
{
|
||||
swapChain = _engine->createSwapChain((void *)window, filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT | filament::backend::SWAP_CHAIN_CONFIG_READABLE);
|
||||
Log("Created window swapchain.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Created headless swapchain %dx%d.", width, height);
|
||||
swapChain = _engine->createSwapChain(width, height, filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT | filament::backend::SWAP_CHAIN_CONFIG_READABLE | filament::SwapChain::CONFIG_HAS_STENCIL_BUFFER);
|
||||
}
|
||||
swapChain = _engine->createSwapChain(width, height, filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT | filament::backend::SWAP_CHAIN_CONFIG_READABLE | filament::SwapChain::CONFIG_HAS_STENCIL_BUFFER);
|
||||
_swapChains.push_back(swapChain);
|
||||
return swapChain;
|
||||
}
|
||||
@@ -734,13 +740,13 @@ namespace thermion
|
||||
void FilamentViewer::destroySwapChain(SwapChain *swapChain)
|
||||
{
|
||||
std::lock_guard lock(_renderMutex);
|
||||
_renderable[swapChain].clear();
|
||||
auto it = std::find(_swapChains.begin(), _swapChains.end(), swapChain);
|
||||
if (it != _swapChains.end())
|
||||
{
|
||||
_swapChains.erase(it);
|
||||
}
|
||||
_engine->destroy(swapChain);
|
||||
Log("Swapchain destroyed.");
|
||||
#ifdef __EMSCRIPTEN__
|
||||
_engine->execute();
|
||||
#else
|
||||
@@ -1016,53 +1022,49 @@ namespace thermion
|
||||
}
|
||||
}
|
||||
|
||||
bool FilamentViewer::render(
|
||||
uint64_t frameTimeInNanos,
|
||||
SwapChain *swapChain,
|
||||
void *pixelBuffer,
|
||||
void (*callback)(void *buf, size_t size, void *data),
|
||||
void *data)
|
||||
void FilamentViewer::setRenderable(View* view, SwapChain* swapChain, bool renderable) {
|
||||
|
||||
std::lock_guard lock(_renderMutex);
|
||||
|
||||
auto views = _renderable[swapChain];
|
||||
|
||||
auto it = std::find(views.begin(), views.end(), view);
|
||||
|
||||
if(renderable) {
|
||||
if(it == views.end()) {
|
||||
views.push_back(view);
|
||||
}
|
||||
} else {
|
||||
if(it != views.end()) {
|
||||
views.erase(it);
|
||||
}
|
||||
}
|
||||
_renderable[swapChain] = views;
|
||||
}
|
||||
|
||||
|
||||
void FilamentViewer::render(
|
||||
uint64_t frameTimeInNanos)
|
||||
{
|
||||
|
||||
if (!swapChain)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
auto secsSinceLastFpsCheck = float(std::chrono::duration_cast<std::chrono::seconds>(now - _fpsCounterStartTime).count());
|
||||
|
||||
if (secsSinceLastFpsCheck >= 1)
|
||||
{
|
||||
auto fps = _frameCount / secsSinceLastFpsCheck;
|
||||
_frameCount = 0;
|
||||
_skippedFrames = 0;
|
||||
_fpsCounterStartTime = now;
|
||||
}
|
||||
|
||||
Timer tmr;
|
||||
|
||||
_sceneManager->updateTransforms();
|
||||
_sceneManager->updateAnimations();
|
||||
|
||||
_cumulativeAnimationUpdateTime += tmr.elapsed();
|
||||
|
||||
// Render the scene, unless the renderer wants to skip the frame.
|
||||
bool beginFrame = _renderer->beginFrame(swapChain, frameTimeInNanos);
|
||||
if (!beginFrame)
|
||||
{
|
||||
_skippedFrames++;
|
||||
} else {
|
||||
for(auto *view : _renderable) {
|
||||
_renderer->render(view);
|
||||
for(auto swapChain : _swapChains) {
|
||||
auto views = _renderable[swapChain];
|
||||
if(views.size() > 0) {
|
||||
bool beginFrame = _renderer->beginFrame(swapChain, frameTimeInNanos);
|
||||
if (beginFrame) {
|
||||
for(auto view : views) {
|
||||
_renderer->render(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
_frameCount++;
|
||||
_renderer->endFrame();
|
||||
}
|
||||
#ifdef __EMSCRIPTEN__
|
||||
_engine->execute();
|
||||
#endif
|
||||
return beginFrame;
|
||||
}
|
||||
|
||||
class CaptureCallbackHandler : public filament::backend::CallbackHandler
|
||||
|
||||
@@ -44,8 +44,9 @@ extern "C"
|
||||
filament::math::float4{float(d_mat.col4[0]), float(d_mat.col4[1]), float(d_mat.col4[2]), float(d_mat.col4[3])}};
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TViewer *create_filament_viewer(const void *context, const void *const loader, void *const platform, const char *uberArchivePath)
|
||||
EMSCRIPTEN_KEEPALIVE TViewer *Viewer_create(const void *context, const void *const loader, void *const platform, const char *uberArchivePath)
|
||||
{
|
||||
Log("CREATE");
|
||||
const auto *loaderImpl = new ResourceLoaderWrapperImpl((ResourceLoaderWrapper *)loader);
|
||||
auto viewer = new FilamentViewer(context, loaderImpl, platform, uberArchivePath);
|
||||
return reinterpret_cast<TViewer *>(viewer);
|
||||
@@ -339,29 +340,18 @@ extern "C"
|
||||
cam->setModelMatrix(mat);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool Viewer_render(
|
||||
TViewer *tViewer,
|
||||
TSwapChain *tSwapChain,
|
||||
uint64_t frameTimeInNanos,
|
||||
void *pixelBuffer,
|
||||
void (*callback)(void *buf, size_t size, void *data),
|
||||
void *data)
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_render(
|
||||
TViewer *tViewer)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto swapChain = reinterpret_cast<SwapChain *>(tSwapChain);
|
||||
|
||||
if(!swapChain) {
|
||||
swapChain = viewer->getSwapChainAt(0);
|
||||
}
|
||||
|
||||
return viewer->render(frameTimeInNanos, swapChain, pixelBuffer, callback, data);
|
||||
viewer->render(0);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_markViewRenderable(TViewer *tViewer, TView* tView, bool renderable) {
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_setViewRenderable(TViewer *tViewer, TSwapChain *tSwapChain, TView *tView, bool renderable) {
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
|
||||
auto swapChain = reinterpret_cast<SwapChain*>(tSwapChain);
|
||||
auto *view = reinterpret_cast<View*>(tView);
|
||||
viewer->setRenderable(view, renderable);
|
||||
viewer->setRenderable(view, swapChain, renderable);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_capture(
|
||||
@@ -416,10 +406,17 @@ extern "C"
|
||||
viewer->destroySwapChain(swapChain);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createSwapChain(TViewer *tViewer, const void *const window, uint32_t width, uint32_t height)
|
||||
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createHeadlessSwapChain(TViewer *tViewer, uint32_t width, uint32_t height)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto swapChain = viewer->createSwapChain(window, width, height);
|
||||
auto swapChain = viewer->createSwapChain(width, height);
|
||||
return reinterpret_cast<TSwapChain *>(swapChain);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createSwapChain(TViewer *tViewer, const void *const window)
|
||||
{
|
||||
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
||||
auto swapChain = viewer->createSwapChain(window);
|
||||
return reinterpret_cast<TSwapChain *>(swapChain);
|
||||
}
|
||||
|
||||
@@ -721,7 +718,8 @@ extern "C"
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_queueTransformUpdates(TSceneManager *tSceneManager, EntityId *entities, const double *const transforms, int numEntities)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
math::mat4 matrices[numEntities];
|
||||
math::mat4 matrices[
|
||||
numEntities];
|
||||
for (int i = 0; i < numEntities; i++)
|
||||
{
|
||||
matrices[i] = math::mat4(
|
||||
|
||||
@@ -82,10 +82,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void requestFrame(TSwapChain* tSwapChain, void (*callback)())
|
||||
void requestFrame(void (*callback)())
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
this->swapChain = tSwapChain;
|
||||
this->_requestFrameRenderCallback = callback;
|
||||
}
|
||||
|
||||
@@ -93,12 +92,12 @@ public:
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
if (swapChain)
|
||||
if (_requestFrameRenderCallback)
|
||||
{
|
||||
doRender(swapChain);
|
||||
doRender();
|
||||
lock.unlock();
|
||||
this->_requestFrameRenderCallback();
|
||||
swapChain = nullptr;
|
||||
this->_requestFrameRenderCallback = nullptr;
|
||||
|
||||
// Calculate and print FPS
|
||||
auto currentTime = std::chrono::high_resolution_clock::now();
|
||||
@@ -158,10 +157,13 @@ public:
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
// emscripten_webgl_commit_frame();
|
||||
|
||||
_viewer = (FilamentViewer *)create_filament_viewer((void *const)_context, loader, platform, uberArchivePath);
|
||||
_viewer = (FilamentViewer *)Viewer_create((void *const)_context, loader, platform, uberArchivePath);
|
||||
MAIN_THREAD_EM_ASM({ moduleArg.dartFilamentResolveCallback($0, $1); }, callback, _viewer);
|
||||
#else
|
||||
auto viewer = (FilamentViewer *)create_filament_viewer(context, loader, platform, uberArchivePath);
|
||||
Log("CREATING1");
|
||||
|
||||
auto viewer = (FilamentViewer *)Viewer_create(context, loader, platform, uberArchivePath);
|
||||
Log("CREATING2");
|
||||
_viewer = reinterpret_cast<TViewer*>(viewer);
|
||||
callback(_viewer);
|
||||
#endif
|
||||
@@ -180,26 +182,13 @@ public:
|
||||
fut.wait();
|
||||
}
|
||||
|
||||
bool doRender(TSwapChain *tSwapChain)
|
||||
void doRender()
|
||||
{
|
||||
#ifdef __EMSCRIPTEN__
|
||||
if (emscripten_is_webgl_context_lost(_context) == EM_TRUE)
|
||||
{
|
||||
Log("Context lost");
|
||||
auto sleepFor = std::chrono::seconds(1);
|
||||
std::this_thread::sleep_for(sleepFor);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
bool rendered = Viewer_render(_viewer, tSwapChain, 0, nullptr, nullptr, nullptr);
|
||||
Viewer_render(_viewer);
|
||||
if (_renderCallback)
|
||||
{
|
||||
_renderCallback(_renderCallbackOwner);
|
||||
}
|
||||
return rendered;
|
||||
#ifdef __EMSCRIPTEN__
|
||||
// emscripten_webgl_commit_frame();
|
||||
#endif
|
||||
}
|
||||
|
||||
void setFrameIntervalInMilliseconds(float frameIntervalInMilliseconds)
|
||||
@@ -251,7 +240,7 @@ extern "C"
|
||||
|
||||
static RenderLoop *_rl;
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void create_filament_viewer_render_thread(
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createOnRenderThread(
|
||||
void *const context, void *const platform, const char *uberArchivePath,
|
||||
const void *const loader,
|
||||
void (*renderCallback)(void *const renderCallbackOwner),
|
||||
@@ -274,8 +263,7 @@ extern "C"
|
||||
_rl = nullptr;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createSwapChainRenderThread(TViewer *viewer,
|
||||
void *const surface,
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createHeadlessSwapChainRenderThread(TViewer *viewer,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
void (*onComplete)(TSwapChain*))
|
||||
@@ -283,12 +271,21 @@ extern "C"
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]() mutable
|
||||
{
|
||||
auto *swapChain = Viewer_createSwapChain(viewer, surface, width, height);
|
||||
#ifdef __EMSCRIPTEN__
|
||||
MAIN_THREAD_EM_ASM({ moduleArg.dartFilamentResolveCallback($0); }, onComplete);
|
||||
#else
|
||||
auto *swapChain = Viewer_createHeadlessSwapChain(viewer, width, height);
|
||||
onComplete(swapChain);
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createSwapChainRenderThread(TViewer *viewer,
|
||||
void *const surface,
|
||||
void (*onComplete)(TSwapChain*))
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]() mutable
|
||||
{
|
||||
auto *swapChain = Viewer_createSwapChain(viewer, surface);
|
||||
onComplete(swapChain);
|
||||
#endif
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
@@ -309,7 +306,7 @@ extern "C"
|
||||
}
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_requestFrameRenderThread(TViewer *viewer, TSwapChain* tSwapChain, void(*onComplete)())
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_requestFrameRenderThread(TViewer *viewer, void(*onComplete)())
|
||||
{
|
||||
if (!_rl)
|
||||
{
|
||||
@@ -317,7 +314,7 @@ extern "C"
|
||||
}
|
||||
else
|
||||
{
|
||||
_rl->requestFrame(tSwapChain, onComplete);
|
||||
_rl->requestFrame(onComplete);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,7 +331,7 @@ extern "C"
|
||||
{
|
||||
std::packaged_task<void()> lambda([=]() mutable
|
||||
{
|
||||
_rl->doRender(tSwapChain);
|
||||
_rl->doRender();
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user