summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/wasm/qwasmcompositor.cpp
diff options
context:
space:
mode:
authorMorten Sørvig <morten.sorvig@qt.io>2024-12-02 15:15:43 +0100
committerMorten Sørvig <morten.sorvig@qt.io>2025-03-03 18:24:43 +0100
commit89d5b96b45de7cb58bc1f364f49e15b96c4e0a4a (patch)
tree823e93063c2d95c9ac35aa2b6097ed1512b7cafc /src/plugins/platforms/wasm/qwasmcompositor.cpp
parent9df167a013b6db0957e35d3924e331a145d518b2 (diff)
wasm: improve asyncify support
Rewrite the event dispatcher to use QWasmSuspendResumeControl for asyncify suspend/resume. This includes using the following helper classes which provides additional functionality on top of QWasmSuspendResumeControl. - QWasmTimer: manages native timers on the main thread - QWasmEventHandler and qstdweb::EventCallback: input events - QWasmAnimationFrameHandler: animation frame events Initialization differs slightly, depending on if QtGui and the QPA machinery is in use, or of the app is a QtCore only application. In the former case, QWasmSuspendResumeControl is created early by QWasmIntegration in order to support registering event handlers at startup, before the event dispatcher has been created. processEvents() now actually processes native events. This is done by running a suspend-resume loop until the native event queue has been exhausted. If WaitForMoreEvents is specified then processEvents() will, in addition, also suspend and wait for additional native events. Timers on secondary threads are now managed by modifying the wait condition timeout, instead of proxying timers to the main thread. In effect secondary threads will now sleep until the next timer should fire, and then wake up and process that timer. Change-Id: I20e8afb6b67c64a7c52dbd89e9c50ffadba39594 Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
Diffstat (limited to 'src/plugins/platforms/wasm/qwasmcompositor.cpp')
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.cpp48
1 files changed, 35 insertions, 13 deletions
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp
index db1fed65d6c..99cf8885af5 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp
@@ -5,6 +5,7 @@
#include "qwasmwindow.h"
#include <private/qeventdispatcher_wasm_p.h>
+#include <private/qwasmsuspendresumecontrol_p.h>
#include <qpa/qwindowsysteminterface.h>
@@ -14,7 +15,13 @@ using namespace emscripten;
bool QWasmCompositor::m_requestUpdateHoldEnabled = false;
-QWasmCompositor::QWasmCompositor(QWasmScreen *screen) : QObject(screen)
+QWasmCompositor::QWasmCompositor(QWasmScreen *screen)
+: QObject(screen)
+, m_animationFrameHandler(QWasmAnimationFrameHandler([this](double frametime){
+ Q_UNUSED(frametime);
+ this->m_requestAnimationFrameId = -1;
+ this->deliverUpdateRequests();
+ }))
{
QWindowSystemInterface::setSynchronousWindowSystemEvents(true);
}
@@ -22,7 +29,7 @@ QWasmCompositor::QWasmCompositor(QWasmScreen *screen) : QObject(screen)
QWasmCompositor::~QWasmCompositor()
{
if (m_requestAnimationFrameId != -1)
- emscripten_cancel_animation_frame(m_requestAnimationFrameId);
+ m_animationFrameHandler.cancelAnimationFrame(m_requestAnimationFrameId);
// TODO(mikolaj.boc): Investigate if m_isEnabled is needed at all. It seems like a frame should
// not be generated after this instead.
@@ -86,17 +93,7 @@ void QWasmCompositor::requestUpdate()
if (m_requestUpdateHoldEnabled)
return;
- static auto frame = [](double frameTime, void *context) -> EM_BOOL {
- Q_UNUSED(frameTime);
-
- QWasmCompositor *compositor = reinterpret_cast<QWasmCompositor *>(context);
-
- compositor->m_requestAnimationFrameId = -1;
- compositor->deliverUpdateRequests();
-
- return EM_FALSE;
- };
- m_requestAnimationFrameId = emscripten_request_animation_frame(frame, this);
+ m_requestAnimationFrameId = m_animationFrameHandler.requestAnimationFrame();
}
void QWasmCompositor::deliverUpdateRequests()
@@ -168,3 +165,28 @@ QWasmScreen *QWasmCompositor::screen()
{
return static_cast<QWasmScreen *>(parent());
}
+
+QWasmAnimationFrameHandler::QWasmAnimationFrameHandler(std::function<void(double)> handler)
+{
+ auto argCastWrapper = [handler](val arg){ handler(arg.as<double>()); };
+ m_handlerIndex = QWasmSuspendResumeControl::get()->registerEventHandler(argCastWrapper);
+}
+
+QWasmAnimationFrameHandler::~QWasmAnimationFrameHandler()
+{
+ QWasmSuspendResumeControl::get()->removeEventHandler(m_handlerIndex);
+}
+
+int64_t QWasmAnimationFrameHandler::requestAnimationFrame()
+{
+ using ReturnType = double; // FIXME emscripten::val::call() does not support int64_t
+ val handler = QWasmSuspendResumeControl::get()->jsEventHandlerAt(m_handlerIndex);
+ return int64_t(val::global("window").call<ReturnType>("requestAnimationFrame", handler));
+}
+
+void QWasmAnimationFrameHandler::cancelAnimationFrame(int64_t id)
+{
+ val::global("window").call<void>("cancelAnimationFrame", double(id));
+}
+
+