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>
34 static std::uint64_t lastIdValue = 0;
35 static_assert(
sizeof(
std::uint64_t) ==
sizeof(
std::uintptr_t),
"uintptr_t size mismatch");
36 auto vsyncIdValue = lastIdValue;
38 return VsyncId(vsyncIdValue);
41std::string generateVSyncName(::OHNativeWindow *nativeWindow,
VsyncId id)
43 return QtOhos::printfToString(
"__qt_vsync_%p_%lu", nativeWindow, id.value());
46class QOhosVSyncRegistry
49 static QOhosVSyncRegistry &instance();
51 std::function<
void()> create(
52 ::OHNativeWindow *nativeWindow,
std::function<
void()> vsyncFrameReadyFunc);
55 static void frameCallback(
long long timestamp,
void *userData);
59 std::function<
void()> vsyncFrameReadyFunc;
60 std::shared_ptr<::OH_NativeVSync> vsync;
64 void notifyFrameReadyFromAnyThread(
VsyncId id);
66 std::map<VsyncId, std::shared_ptr<VSyncContext>> m_registry;
67 QOhosConsumer<VsyncId> m_notifyFrameReadyFromAnyThread;
70QOhosVSyncRegistry &QOhosVSyncRegistry::instance()
72 static QOhosVSyncRegistry result;
76void QOhosVSyncRegistry::frameCallback(
long long,
void *userData)
78 auto vsyncId = VsyncId(
reinterpret_cast<
std::uintptr_t>(userData));
79 instance().m_notifyFrameReadyFromAnyThread(vsyncId);
82std::function<
void()> QOhosVSyncRegistry::create(
83 ::OHNativeWindow *nativeWindow,
std::function<
void()> vsyncFrameReadyFunc)
85 auto vsyncId = generateVsyncId();
86 auto vsyncName = generateVSyncName(nativeWindow, vsyncId);
88 std::uint64_t surfaceId = 0;
89 callArkUiOrFailOnErrorResult(
90 Q_OHOS_NAMED_FUNC(::OH_NativeWindow_GetSurfaceId),
91 nativeWindow, &surfaceId);
93 auto vsync = std::shared_ptr<::OH_NativeVSync>(
94 callArkUiOrFailOnNullResult(
95 Q_OHOS_NAMED_FUNC(::OH_NativeVSync_Create_ForAssociatedWindow),
96 surfaceId, vsyncName.c_str(), vsyncName.length()),
97 [](::OH_NativeVSync *vsync) {
99 Q_OHOS_NAMED_FUNC(::OH_NativeVSync_Destroy),
103 auto context = QtOhos::moveToSharedPtr(
105 .vsyncFrameReadyFunc = std::move(vsyncFrameReadyFunc),
109 m_registry.emplace(vsyncId, context);
111 auto contextWithDeleter =
112 QtOhos::makeSharedPtrWithAttachedExtraData(
114 QtOhos::makeDestroyNotifier(
116 std::ignore = m_registry.erase(vsyncId);
119 return [vsyncId, contextWithDeleter]() {
120 callArkUiOrFailOnErrorResult(
121 Q_OHOS_NAMED_FUNC(::OH_NativeVSync_RequestFrame),
122 contextWithDeleter->vsync.get(), &QOhosVSyncRegistry::frameCallback,
123 reinterpret_cast<
void *>(vsyncId.value()));
127QOhosVSyncRegistry::QOhosVSyncRegistry()
129 auto vsyncFrameReadyHandler = makeQtOhosBatchingMTRequestsHandler<std::unordered_set<VsyncId>>(
130 [](std::function<
void()> task) {
131 QtOhos::invokeInJsThread(
132 [task = std::move(task)](QtOhos::JsState &){
136 [
this](std::unordered_set<VsyncId> &&vsyncIds) {
137 for (
auto vsyncId: vsyncIds) {
138 auto vsyncContextIt = m_registry.find(vsyncId);
139 if (vsyncContextIt != m_registry.end()) {
140 auto vsyncContext = vsyncContextIt->second;
141 vsyncContext->vsyncFrameReadyFunc();
146 m_notifyFrameReadyFromAnyThread = [vsyncFrameReadyHandler = std::move(vsyncFrameReadyHandler)](VsyncId vsyncId) {
147 vsyncFrameReadyHandler(
148 [&](std::unordered_set<VsyncId> &vsyncIds) {
149 vsyncIds.insert(vsyncId);
157 ::OHNativeWindow *nativeWindow,
std::function<
void()> vsyncFrameReadyFunc)
159 return QOhosVSyncRegistry::instance().create(nativeWindow,
std::move(vsyncFrameReadyFunc));
166 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