Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions thermion_dart/lib/src/bindings/src/js_interop.dart
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ Future<Pointer<T>> withPointerCallback<T extends NativeType>(

func.call(onComplete_interopFnPtr.cast());


while (!completer.isCompleted) {
_NativeLibrary.instance._execute_queue();
await Future.delayed(Duration(milliseconds: 1));
}

var ptr = await completer.future;
onComplete_interopFnPtr.dispose();

Expand All @@ -120,7 +126,11 @@ Future<bool> withBoolCallback(
final onComplete_interopFnPtr = callback.addFunction();

func.call(onComplete_interopFnPtr.cast());
await completer.future;

while (!completer.isCompleted) {
_NativeLibrary.instance._execute_queue();
await Future.delayed(Duration(milliseconds: 1));
}

return completer.future;
}
Expand All @@ -134,20 +144,26 @@ Future<double> withFloatCallback(
};
var ptr = callback.addFunction();
func.call(ptr);
await completer.future;
while (!completer.isCompleted) {
_NativeLibrary.instance._execute_queue();
await Future.delayed(Duration(milliseconds: 1));
}
return completer.future;
}

Future<int> withIntCallback(
Function(Pointer<NativeFunction<void Function(int)>>) func) async {
final completer = Completer<int>();
final completer = Completer<int>();
// ignore: prefer_function_declarations_over_variables
void Function(int) callback = (int result) {
completer.complete(result);
};
var ptr = callback.addFunction();
func.call(ptr);
await completer.future;
while (!completer.isCompleted) {
_NativeLibrary.instance._execute_queue();
await Future.delayed(Duration(milliseconds: 1));
}
return completer.future;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,14 +289,14 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
await renderManager.detachAll(swapChain);
await destroySwapChain(swapChain);
}

FilamentApp.instance = null;
renderManager.destroy();
await withVoidCallback((requestId, cb) async {
Engine_destroyRenderThread(engine, requestId, cb);
});

RenderThread_destroy();

FilamentApp.instance = null;
for (final callback in _onDestroy) {
await callback.call();
}
Expand Down
16 changes: 13 additions & 3 deletions thermion_dart/native/src/rendering/RenderThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,15 @@ bool loopExitTimeValid = false;

static void mainLoop(void* arg) {
auto *rt = static_cast<RenderThread *>(arg);
if (!rt->mStop) {
rt->iter();
// If the render thread has been asked to stop, break the loop and exit immediately.
if (rt->mStop) {
emscripten_cancel_main_loop();
loopExitTime = std::chrono::high_resolution_clock::now();
loopExitTimeValid = true;
return;
}

rt->iter();
loopExitTime = std::chrono::high_resolution_clock::now();
loopExitTimeValid = true;
}
Expand Down Expand Up @@ -82,7 +88,11 @@ RenderThread::~RenderThread()
_tasks.pop_front();
task();
}
#ifndef __EMSCRIPTEN__

#ifdef __EMSCRIPTEN__
// Waiting for the main loop to exit before continuing
pthread_join(t, nullptr);
#else
t->join();
delete t;
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class ThermionFlutterPluginImpl extends ThermionFlutterPlugin {
static final _descriptors = <PlatformTextureDescriptor>[];
static final _destroyed = <PlatformTextureDescriptor>[];
static final _logger = Logger('ThermionFlutterPluginImpl');
static int? _frameRequestId;

static Future<Uint8List> loadAsset(String path) async {
if (path.startsWith("file://")) {
Expand Down Expand Up @@ -48,13 +49,37 @@ class ThermionFlutterPluginImpl extends ThermionFlutterPlugin {
}
_destroyed.clear();

window.requestAnimationFrame(_tick.toJS);
_frameRequestId = window.requestAnimationFrame(_tick.toJS);
}

static void _ensureFrameLoopRunning() {
_frameRequestId ??= window.requestAnimationFrame(_tick.toJS);
}


static void _resetWebState() {
if (_frameRequestId != null) {
window.cancelAnimationFrame(_frameRequestId!);
_frameRequestId = null;
}

_stackPtr = null;
swapChain = null;
_descriptors.clear();
_destroyed.clear();
}

static SwapChain? swapChain;

@override
Future<SwapChain> initialize({bool destroySwapchain = true}) async {
if (FilamentApp.instance != null && swapChain != null) {
// Hot reload re-enters initialize without disposing the existing web
// engine. Reuse the live app instead of spawning another em-pthread.
_ensureFrameLoopRunning();
return swapChain!;
}

HTMLCanvasElement? canvas;
// first, try and initialize bindings to see if the user has included thermion_dart.js manually in index.html
try {
Expand Down Expand Up @@ -118,6 +143,10 @@ class ThermionFlutterPluginImpl extends ThermionFlutterPlugin {
sharedContext: null,
uberArchivePath: options.uberarchivePath);
await FFIFilamentApp.create(config: config);
// resetting the web state when the app is destroyed
(FilamentApp.instance as FFIFilamentApp).onDestroy(() async {
_resetWebState();
});

// Use createSwapChain with nullptr to render to the canvas's default
// framebuffer (framebuffer 0). createHeadlessSwapChain creates an offscreen
Expand All @@ -126,7 +155,7 @@ class ThermionFlutterPluginImpl extends ThermionFlutterPlugin {

print("Created 1x1 headless swapchain");

window.requestAnimationFrame(_tick.toJS);
_ensureFrameLoopRunning();

return swapChain!;
}
Expand Down
Loading