1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "vsync_station.h"
17
18#include <unistd.h>
19#include "transaction/rs_interfaces.h"
20#include "window_manager_hilog.h"
21
22
23namespace OHOS {
24namespace Rosen {
25namespace {
26constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "VsyncStation"};
27}
28
29VsyncStation::VsyncStation(NodeId nodeId) : nodeId_(nodeId)
30{
31    TLOGI(WmsLogTag::WMS_MAIN, "Vsync Constructor");
32}
33
34void VsyncStation::RequestVsync(const std::shared_ptr<VsyncCallback>& vsyncCallback)
35{
36    {
37        std::lock_guard<std::mutex> lock(mtx_);
38        if (destroyed_) {
39            return;
40        }
41        vsyncCallbacks_.insert(vsyncCallback);
42
43        if (!hasInitVsyncReceiver_) {
44            auto& rsClient = OHOS::Rosen::RSInterfaces::GetInstance();
45            while (receiver_ == nullptr) {
46                receiver_ = rsClient.CreateVSyncReceiver("WM_" + std::to_string(getpid()), nodeId_);
47                TLOGI(WmsLogTag::WMS_MAIN, "Create vsync receiver for nodeId:%{public}" PRIu64"", nodeId_);
48            }
49            receiver_->Init();
50            hasInitVsyncReceiver_ = true;
51        }
52        if (hasRequestedVsync_) {
53            return;
54        }
55        hasRequestedVsync_ = true;
56    }
57    receiver_->RequestNextVSync(frameCallback_);
58}
59
60int64_t VsyncStation::GetVSyncPeriod()
61{
62    return 0;
63}
64
65void VsyncStation::Init()
66{
67}
68
69void VsyncStation::RemoveCallback()
70{
71    WLOGI("Remove Vsync callback");
72    std::lock_guard<std::mutex> lock(mtx_);
73    vsyncCallbacks_.clear();
74}
75
76void VsyncStation::VsyncCallbackInner(int64_t timestamp, int64_t frameCount)
77{
78    std::unordered_set<std::shared_ptr<VsyncCallback>> vsyncCallbacks;
79    {
80        std::lock_guard<std::mutex> lock(mtx_);
81        hasRequestedVsync_ = false;
82        vsyncCallbacks = vsyncCallbacks_;
83        vsyncCallbacks_.clear();
84    }
85    for (const auto& callback: vsyncCallbacks) {
86        callback->onCallback(timestamp, frameCount);
87    }
88}
89
90void VsyncStation::OnVsync(int64_t timestamp, int64_t frameCount, void* client)
91{
92    auto vsyncClient = static_cast<VsyncStation*>(client);
93    if (vsyncClient) {
94        vsyncClient->VsyncCallbackInner(timestamp, frameCount);
95    } else {
96        WLOGFE("VsyncClient is null");
97    }
98}
99
100void VsyncStation::OnVsyncTimeOut()
101{
102    WLOGW("Vsync time out");
103    std::lock_guard<std::mutex> lock(mtx_);
104    hasRequestedVsync_ = false;
105}
106}
107}
108