4#include <qarkui/vsync.h>
10#include <native_vsync/native_vsync.h>
11#include <native_window/external_window.h>
12#include <qarkui/qarkuiutils.h>
13#include <qohosplugincore.h>
14#include <qohosutils.h>
15#include <render/qohosbatchingrequestshandler.h>
16#include <unordered_set>
35 static std::uint64_t lastIdValue = 0;
36 static_assert(
sizeof(
std::uint64_t) ==
sizeof(
std::uintptr_t),
"uintptr_t size mismatch");
37 auto vsyncIdValue = lastIdValue;
39 return VsyncId(vsyncIdValue);
42std::string generateVSyncName(::OHNativeWindow *nativeWindow,
VsyncId id)
44 return QtOhos::printfToString(
"__qt_vsync_%p_%lu", nativeWindow, id.value());
47class QOhosVSyncRegistry
50 static QOhosVSyncRegistry &instance();
52 std::function<
void()> create(
53 ::OHNativeWindow *nativeWindow,
std::function<
void()> vsyncFrameReadyFunc);
56 static void frameCallback(
long long timestamp,
void *userData);
60 std::function<
void()> vsyncFrameReadyFunc;
61 std::shared_ptr<::OH_NativeVSync> vsync;
65 void notifyFrameReadyFromAnyThread(
VsyncId id);
67 std::map<VsyncId, std::shared_ptr<VSyncContext>> m_registry;
68 QOhosConsumer<VsyncId> m_notifyFrameReadyFromAnyThread;
71QOhosVSyncRegistry &QOhosVSyncRegistry::instance()
73 static QOhosVSyncRegistry result;
77void QOhosVSyncRegistry::frameCallback(
long long,
void *userData)
79 auto vsyncId = VsyncId(
reinterpret_cast<
std::uintptr_t>(userData));
80 instance().m_notifyFrameReadyFromAnyThread(vsyncId);
83std::function<
void()> QOhosVSyncRegistry::create(
84 ::OHNativeWindow *nativeWindow,
std::function<
void()> vsyncFrameReadyFunc)
86 auto vsyncId = generateVsyncId();
87 auto vsyncName = generateVSyncName(nativeWindow, vsyncId);
89 std::uint64_t surfaceId = 0;
90 callArkUiOrFailOnErrorResult(
91 Q_OHOS_NAMED_FUNC(::OH_NativeWindow_GetSurfaceId),
92 nativeWindow, &surfaceId);
94 auto vsync = std::shared_ptr<::OH_NativeVSync>(
95 callArkUiOrFailOnNullResult(
96 Q_OHOS_NAMED_FUNC(::OH_NativeVSync_Create_ForAssociatedWindow),
97 surfaceId, vsyncName.c_str(), vsyncName.length()),
98 [](::OH_NativeVSync *vsync) {
100 Q_OHOS_NAMED_FUNC(::OH_NativeVSync_Destroy),
104 auto context = QtOhos::moveToSharedPtr(
106 .vsyncFrameReadyFunc = std::move(vsyncFrameReadyFunc),
110 m_registry.emplace(vsyncId, context);
112 auto contextWithDeleter =
113 QtOhos::makeSharedPtrWithAttachedExtraData(
115 QtOhos::makeDestroyNotifier(
117 std::ignore = m_registry.erase(vsyncId);
120 return [vsyncId, contextWithDeleter]() {
121 callArkUiOrFailOnErrorResult(
122 Q_OHOS_NAMED_FUNC(::OH_NativeVSync_RequestFrame),
123 contextWithDeleter->vsync.get(), &QOhosVSyncRegistry::frameCallback,
124 reinterpret_cast<
void *>(vsyncId.value()));
128QOhosVSyncRegistry::QOhosVSyncRegistry()
130 auto vsyncFrameReadyHandler = makeQtOhosBatchingMTRequestsHandler<std::unordered_set<VsyncId>>(
131 [](std::function<
void()> task) {
132 QtOhos::invokeInJsThread(
133 [task = std::move(task)](QtOhos::JsState &){
137 [
this](std::unordered_set<VsyncId> &&vsyncIds) {
138 for (
auto vsyncId: vsyncIds) {
139 auto vsyncContextIt = m_registry.find(vsyncId);
140 if (vsyncContextIt != m_registry.end()) {
141 auto vsyncContext = vsyncContextIt->second;
142 vsyncContext->vsyncFrameReadyFunc();
147 m_notifyFrameReadyFromAnyThread = [vsyncFrameReadyHandler = std::move(vsyncFrameReadyHandler)](VsyncId vsyncId) {
148 vsyncFrameReadyHandler(
149 [&](std::unordered_set<VsyncId> &vsyncIds) {
150 vsyncIds.insert(vsyncId);
158 ::OHNativeWindow *nativeWindow,
std::function<
void()> vsyncFrameReadyFunc)
160 return QOhosVSyncRegistry::instance().create(nativeWindow,
std::move(vsyncFrameReadyFunc));
167 return vsyncId.value();
std::function< void()> makeVSyncFrameRequester(::OHNativeWindow *nativeWindow, std::function< void()> vsyncFrameReadyFunc)
std::size_t operator()(const VsyncId &vsyncId) const noexcept
QtOhos::TypedId< std::uintptr_t, struct VsyncIdTag > VsyncId