diff options
| author | Morten Sørvig <morten.sorvig@qt.io> | 2024-12-02 15:15:43 +0100 |
|---|---|---|
| committer | Morten Sørvig <morten.sorvig@qt.io> | 2025-03-03 18:24:43 +0100 |
| commit | 89d5b96b45de7cb58bc1f364f49e15b96c4e0a4a (patch) | |
| tree | 823e93063c2d95c9ac35aa2b6097ed1512b7cafc /src/plugins/platforms/wasm/qwasmcompositor.cpp | |
| parent | 9df167a013b6db0957e35d3924e331a145d518b2 (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.cpp | 48 |
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)); +} + + |
