• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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_receiver.h"
17 #include <memory>
18 #include <mutex>
19 #include <unistd.h>
20 #include <scoped_bytrace.h>
21 #include <fcntl.h>
22 #include <hitrace_meter.h>
23 #include "graphic_common.h"
24 #include "rs_frame_report_ext.h"
25 #include "vsync_log.h"
26 #include <rs_trace.h>
27 
28 namespace OHOS {
29 namespace Rosen {
OnReadable(int32_t fileDescriptor)30 void VSyncCallBackListener::OnReadable(int32_t fileDescriptor)
31 {
32     HitracePerfScoped perfTrace(ScopedDebugTrace::isEnabled(), HITRACE_TAG_GRAPHIC_AGP, "OnReadablePerfCount");
33     {
34         std::lock_guard<std::mutex> locker(cbMutex_);
35         if (fileDescriptor < 0 || (readableCallback_ != nullptr && !readableCallback_(fileDescriptor))) {
36             VLOGE("OnReadable Invalid fileDescriptor:%{public}d", fileDescriptor);
37             return;
38         }
39     }
40     // 3 is array size.
41     int64_t data[3];
42     ssize_t dataCount = 0;
43     if (ReadFdInternal(fileDescriptor, data, dataCount) != VSYNC_ERROR_OK) {
44         return;
45     }
46     HandleVsyncCallbacks(data, dataCount, fileDescriptor);
47 }
48 
OnShutdown(int32_t fileDescriptor)49 void VSyncCallBackListener::OnShutdown(int32_t fileDescriptor)
50 {
51     VLOGI("OnShutdown, fileDescriptor:%{public}d", fileDescriptor);
52     std::lock_guard<std::mutex> locker(cbMutex_);
53     if (fdShutDownCallback_ != nullptr) {
54         fdShutDownCallback_(fileDescriptor);
55     }
56 }
57 
ReadFdInternal(int32_t fd,int64_t (& data)[3],ssize_t & dataCount)58 VsyncError VSyncCallBackListener::ReadFdInternal(int32_t fd, int64_t (&data)[3], ssize_t &dataCount)
59 {
60     std::lock_guard<std::mutex> locker(fdMutex_);
61     if (fdClosed_) {
62         return VSYNC_ERROR_API_FAILED;
63     }
64     ssize_t ret = 0;
65     do {
66         // only take the latest timestamp
67         ret = read(fd, data, sizeof(data));
68         if (ret == 0) {
69             VLOGE("ReadFdInternal, ret is 0, read fd:%{public}d failed, errno:%{public}d", fd, errno);
70             return VSYNC_ERROR_OK;
71         }
72         if (ret == -1) {
73             if (errno == EINTR) {
74                 ret = 0;
75                 continue;
76             } else if (errno != EAGAIN) {
77                 VLOGE("ReadFdInternal, read fd:%{public}d failed, errno:%{public}d", fd, errno);
78             }
79         } else {
80             dataCount += ret;
81         }
82     } while (ret != -1);
83 
84     return VSYNC_ERROR_OK;
85 }
86 
HandleVsyncCallbacks(int64_t data[],ssize_t dataCount,int32_t fileDescriptor)87 void VSyncCallBackListener::HandleVsyncCallbacks(int64_t data[], ssize_t dataCount, int32_t fileDescriptor)
88 {
89     VSyncCallback cb = nullptr;
90     VSyncCallbackWithId cbWithId = nullptr;
91     void *userData = nullptr;
92     int64_t now = 0;
93     int64_t expectedEnd = 0;
94     std::vector<FrameCallback> callbacks;
95     {
96         std::lock_guard<std::mutex> locker(mtx_);
97         cb = vsyncCallbacks_;
98         cbWithId = vsyncCallbacksWithId_;
99         userData = userData_;
100         RNVFlag_ = false;
101         now = data[0];
102         period_ = data[1];
103         periodShared_ = data[1];
104         timeStamp_ = data[0];
105         timeStampShared_ = data[0];
106         expectedEnd = CalculateExpectedEndLocked(now);
107         callbacks = frameCallbacks_;
108         frameCallbacks_.clear();
109     }
110 
111     VLOGD("dataCount:%{public}d, cb == nullptr:%{public}d", dataCount, (cb == nullptr));
112     // 1, 2: index of array data.
113     RS_TRACE_NAME_FMT("ReceiveVsync name:%s dataCount: %ldbytes now: %ld expectedEnd: %ld vsyncId: %ld, fd:%d",
114         name_.c_str(), dataCount, now, expectedEnd, data[2], fileDescriptor); // data[2] is vsyncId
115     if (callbacks.empty() && dataCount > 0 && (cbWithId != nullptr || cb != nullptr)) {
116         // data[2] is frameCount
117         cbWithId != nullptr ? cbWithId(now, data[2], userData) : cb(now, userData);
118     }
119     for (const auto& cb : callbacks) {
120         if (cb.callback_ != nullptr) {
121             cb.callback_(now, cb.userData_);
122         } else if (cb.callbackWithId_ != nullptr) {
123             cb.callbackWithId_(now, data[2], cb.userData_); // data[2] is vsyncId
124         }
125     }
126     if (OHOS::Rosen::RsFrameReportExt::GetInstance().GetEnable()) {
127         OHOS::Rosen::RsFrameReportExt::GetInstance().ReceiveVSync();
128     }
129 }
130 
CalculateExpectedEndLocked(int64_t now)131 int64_t VSyncCallBackListener::CalculateExpectedEndLocked(int64_t now)
132 {
133     int64_t expectedEnd = 0;
134     if (period_ < 0 || now < period_ || now > INT64_MAX - period_) {
135         RS_TRACE_NAME_FMT("invalid timestamps, now:%ld, period_:%ld", now, period_);
136         VLOGE("invalid timestamps, now:" VPUBI64 ", period_:" VPUBI64, now, period_);
137         return 0;
138     }
139     expectedEnd = now + period_;
140     if (name_ == "rs") {
141         // rs vsync offset is 5000000ns
142         expectedEnd = expectedEnd + period_ - 5000000;
143     }
144     return expectedEnd;
145 }
146 
SetFdClosedFlagLocked(bool fdClosed)147 void VSyncCallBackListener::SetFdClosedFlagLocked(bool fdClosed)
148 {
149     fdClosed_ = fdClosed;
150 }
151 
RegisterFdShutDownCallback(FdShutDownCallback cb)152 void VSyncCallBackListener::RegisterFdShutDownCallback(FdShutDownCallback cb)
153 {
154     std::lock_guard<std::mutex> locker(cbMutex_);
155     fdShutDownCallback_ = cb;
156 }
157 
RegisterReadableCallback(ReadableCallback cb)158 void VSyncCallBackListener::RegisterReadableCallback(ReadableCallback cb)
159 {
160     std::lock_guard<std::mutex> locker(cbMutex_);
161     readableCallback_ = cb;
162 }
163 } // namespace Rosen
164 } // namespace OHOS
165