1 /*
2 * Copyright (c) 2021 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_generator.h"
17 #include <cstdint>
18 #include <mutex>
19 #include <scoped_bytrace.h>
20 #include <sched.h>
21 #include <sys/resource.h>
22 #include <string>
23 #include "vsync_log.h"
24
25 namespace OHOS {
26 namespace Rosen {
27 namespace impl {
28 namespace {
GetSysTimeNs()29 static int64_t GetSysTimeNs()
30 {
31 auto now = std::chrono::steady_clock::now().time_since_epoch();
32 return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
33 }
34
35 // 1.5ms
36 constexpr int64_t maxWaleupDelay = 1500000;
37 constexpr int32_t THREAD_PRIORTY = -6;
38 constexpr int32_t SCHED_PRIORITY = 2;
39 constexpr int64_t errorThreshold = 500000;
40 constexpr int32_t MAX_REFRESHRATE_DEVIATION = 5; // ±5Hz
41 constexpr int64_t MAX_TIMESTAMP_THRESHOLD = 1000000; // 1000000ns == 1.0ms
42
SetThreadHighPriority()43 static void SetThreadHighPriority()
44 {
45 setpriority(PRIO_PROCESS, 0, THREAD_PRIORTY);
46 struct sched_param param = {0};
47 param.sched_priority = SCHED_PRIORITY;
48 sched_setscheduler(0, SCHED_FIFO, ¶m);
49 }
50 }
51
52 std::once_flag VSyncGenerator::createFlag_;
53 sptr<OHOS::Rosen::VSyncGenerator> VSyncGenerator::instance_ = nullptr;
54
GetInstance()55 sptr<OHOS::Rosen::VSyncGenerator> VSyncGenerator::GetInstance() noexcept
56 {
57 std::call_once(createFlag_, []() {
58 auto vsyncGenerator = new VSyncGenerator();
59 instance_ = vsyncGenerator;
60 });
61
62 return instance_;
63 }
64
DeleteInstance()65 void VSyncGenerator::DeleteInstance() noexcept
66 {
67 instance_ = nullptr;
68 }
69
VSyncGenerator()70 VSyncGenerator::VSyncGenerator()
71 : period_(0), phase_(0), referenceTime_(0), wakeupDelay_(0),
72 pulse_(0), currRefreshRate_(0), referenceTimeOffsetPulseNum_(0), defaultReferenceTimeOffsetPulseNum_(0)
73 {
74 vsyncThreadRunning_ = true;
75 thread_ = std::thread(std::bind(&VSyncGenerator::ThreadLoop, this));
76 pthread_setname_np(thread_.native_handle(), "VSyncGenerator");
77 }
78
~VSyncGenerator()79 VSyncGenerator::~VSyncGenerator()
80 {
81 {
82 std::unique_lock<std::mutex> locker(mutex_);
83 vsyncThreadRunning_ = false;
84 }
85 if (thread_.joinable()) {
86 con_.notify_all();
87 thread_.join();
88 }
89 }
90
ListenerVsyncEventCB(int64_t occurTimestamp,int64_t nextTimeStamp,int64_t occurReferenceTime,bool isWakeup)91 void VSyncGenerator::ListenerVsyncEventCB(int64_t occurTimestamp, int64_t nextTimeStamp,
92 int64_t occurReferenceTime, bool isWakeup)
93 {
94 std::vector<Listener> listeners;
95 {
96 std::unique_lock<std::mutex> locker(mutex_);
97 int64_t newOccurTimestamp = GetSysTimeNs();
98 if (isWakeup) {
99 UpdateWakeupDelay(newOccurTimestamp, nextTimeStamp);
100 }
101 if (vsyncMode_ == VSYNC_MODE_LTPO) {
102 listeners = GetListenerTimeoutedLTPO(occurTimestamp, occurReferenceTime);
103 } else {
104 listeners = GetListenerTimeouted(newOccurTimestamp, occurTimestamp, occurReferenceTime);
105 }
106 }
107 ScopedBytrace func("GenerateVsyncCount:" + std::to_string(listeners.size()) +
108 ", period:" + std::to_string(periodRecord_) + ", currRefreshRate_:" + std::to_string(currRefreshRate_) +
109 ", vsyncMode_:" + std::to_string(vsyncMode_));
110 for (uint32_t i = 0; i < listeners.size(); i++) {
111 listeners[i].callback_->OnVSyncEvent(listeners[i].lastTime_, periodRecord_, currRefreshRate_, vsyncMode_);
112 }
113 }
114
ThreadLoop()115 void VSyncGenerator::ThreadLoop()
116 {
117 // set thread priorty
118 SetThreadHighPriority();
119
120 int64_t occurTimestamp = 0;
121 int64_t nextTimeStamp = 0;
122 int64_t occurReferenceTime = 0;
123 while (vsyncThreadRunning_ == true) {
124 {
125 std::unique_lock<std::mutex> locker(mutex_);
126 UpdateVSyncModeLocked();
127 occurReferenceTime = referenceTime_;
128 phaseRecord_ = phase_;
129 periodRecord_ = period_;
130 if (period_ == 0) {
131 ScopedBytrace func("VSyncGenerator: period not valid");
132 if (vsyncThreadRunning_ == true) {
133 con_.wait(locker);
134 }
135 continue;
136 }
137 occurTimestamp = GetSysTimeNs();
138 nextTimeStamp = ComputeNextVSyncTimeStamp(occurTimestamp, occurReferenceTime);
139 if (nextTimeStamp == INT64_MAX) {
140 ScopedBytrace func("VSyncGenerator: there has no listener");
141 if (vsyncThreadRunning_ == true) {
142 con_.wait(locker);
143 }
144 continue;
145 } else if (vsyncMode_ == VSYNC_MODE_LTPO) {
146 bool modelChanged = UpdateChangeDataLocked(occurTimestamp, occurReferenceTime, nextTimeStamp);
147 if (modelChanged) {
148 ScopedBytrace func("VSyncGenerator: LTPO mode change");
149 continue;
150 }
151 }
152 }
153
154 bool isWakeup = false;
155 if (occurTimestamp < nextTimeStamp) {
156 std::unique_lock<std::mutex> lck(waitForTimeoutMtx_);
157 auto err = waitForTimeoutCon_.wait_for(lck, std::chrono::nanoseconds(nextTimeStamp - occurTimestamp));
158 if (err == std::cv_status::timeout) {
159 isWakeup = true;
160 } else {
161 ScopedBytrace func("VSyncGenerator::ThreadLoop::Continue");
162 continue;
163 }
164 }
165 ListenerVsyncEventCB(occurTimestamp, nextTimeStamp, occurReferenceTime, isWakeup);
166 }
167 }
168
ChangeListenerOffsetInternal()169 bool VSyncGenerator::ChangeListenerOffsetInternal()
170 {
171 if (changingPhaseOffset_.cb == nullptr) {
172 return true;
173 }
174 auto it = listeners_.begin();
175 for (; it < listeners_.end(); it++) {
176 if (it->callback_ == changingPhaseOffset_.cb) {
177 break;
178 }
179 }
180 int64_t phaseOffset = pulse_ * changingPhaseOffset_.phaseByPulseNum;
181 if (it != listeners_.end()) {
182 it->phase_ = phaseOffset;
183 }
184
185 it = listenersRecord_.begin();
186 for (; it < listenersRecord_.end(); it++) {
187 if (it->callback_ == changingPhaseOffset_.cb) {
188 break;
189 }
190 }
191 if (it == listenersRecord_.end()) {
192 return false;
193 }
194 it->callback_->OnPhaseOffsetChanged(phaseOffset);
195 changingPhaseOffset_ = {}; // reset
196 return true;
197 }
198
ChangeListenerRefreshRatesInternal()199 bool VSyncGenerator::ChangeListenerRefreshRatesInternal()
200 {
201 if (changingRefreshRates_.cb == nullptr) {
202 return true;
203 }
204 auto it = listenersRecord_.begin();
205 for (; it < listenersRecord_.end(); it++) {
206 if (it->callback_ == changingRefreshRates_.cb) {
207 break;
208 }
209 }
210 if (it == listenersRecord_.end()) {
211 return false;
212 }
213 it->callback_->OnConnsRefreshRateChanged(changingRefreshRates_.refreshRates);
214 // reset
215 changingRefreshRates_.cb = nullptr;
216 changingRefreshRates_.refreshRates.clear();
217 changingRefreshRates_ = {};
218 return true;
219 }
220
UpdateWakeupDelay(int64_t occurTimestamp,int64_t nextTimeStamp)221 void VSyncGenerator::UpdateWakeupDelay(int64_t occurTimestamp, int64_t nextTimeStamp)
222 {
223 // 63, 1 / 64
224 wakeupDelay_ = ((wakeupDelay_ * 63) + (occurTimestamp - nextTimeStamp)) / 64;
225 wakeupDelay_ = wakeupDelay_ > maxWaleupDelay ? maxWaleupDelay : wakeupDelay_;
226 }
227
ComputeNextVSyncTimeStamp(int64_t now,int64_t referenceTime)228 int64_t VSyncGenerator::ComputeNextVSyncTimeStamp(int64_t now, int64_t referenceTime)
229 {
230 int64_t nextVSyncTime = INT64_MAX;
231 for (uint32_t i = 0; i < listeners_.size(); i++) {
232 int64_t t = ComputeListenerNextVSyncTimeStamp(listeners_[i], now, referenceTime);
233 if (t < nextVSyncTime) {
234 nextVSyncTime = t;
235 }
236 }
237
238 return nextVSyncTime;
239 }
240
CheckTimingCorrect(int64_t now,int64_t referenceTime,int64_t nextVSyncTime)241 bool VSyncGenerator::CheckTimingCorrect(int64_t now, int64_t referenceTime, int64_t nextVSyncTime)
242 {
243 bool isTimingCorrect = false;
244 for (uint32_t i = 0; i < listeners_.size(); i++) {
245 int64_t t = ComputeListenerNextVSyncTimeStamp(listeners_[i], now, referenceTime);
246 if ((t - nextVSyncTime < errorThreshold) && (listeners_[i].phase_ == 0)) {
247 isTimingCorrect = true;
248 }
249 }
250 return isTimingCorrect;
251 }
252
UpdateChangeDataLocked(int64_t now,int64_t referenceTime,int64_t nextVSyncTime)253 bool VSyncGenerator::UpdateChangeDataLocked(int64_t now, int64_t referenceTime, int64_t nextVSyncTime)
254 {
255 if (!CheckTimingCorrect(now, referenceTime, nextVSyncTime)) {
256 return false;
257 }
258
259 bool modelChanged = false;
260
261 // update generate refreshRate
262 if (needChangeGeneratorRefreshRate_) {
263 currRefreshRate_ = changingGeneratorRefreshRate_;
264 period_ = pulse_ * static_cast<int64_t>(VSYNC_MAX_REFRESHRATE / currRefreshRate_);
265 referenceTime_ = nextVSyncTime;
266 changingGeneratorRefreshRate_ = 0; // reset
267 needChangeGeneratorRefreshRate_ = false;
268 refreshRateIsChanged_ = true;
269 frameRateChanging_ = true;
270 modelChanged = true;
271 }
272
273 // update phaseOffset
274 if (needChangePhaseOffset_) {
275 bool offsetChangedSucceed = ChangeListenerOffsetInternal();
276 if (offsetChangedSucceed) {
277 needChangePhaseOffset_ = false;
278 modelChanged = true;
279 }
280 }
281
282 // update VSyncConnections refreshRates
283 if (needChangeRefreshRates_) {
284 bool refreshRatesChangedSucceed = ChangeListenerRefreshRatesInternal();
285 if (refreshRatesChangedSucceed) {
286 needChangeRefreshRates_ = false;
287 modelChanged = true;
288 }
289 }
290
291 return modelChanged;
292 }
293
UpdateVSyncModeLocked()294 void VSyncGenerator::UpdateVSyncModeLocked()
295 {
296 if (pendingVsyncMode_ != VSYNC_MODE_INVALID) {
297 vsyncMode_ = pendingVsyncMode_;
298 pendingVsyncMode_ = VSYNC_MODE_INVALID;
299 }
300 }
301
ComputeListenerNextVSyncTimeStamp(const Listener & listener,int64_t now,int64_t referenceTime)302 int64_t VSyncGenerator::ComputeListenerNextVSyncTimeStamp(const Listener& listener, int64_t now, int64_t referenceTime)
303 {
304 int64_t lastVSyncTime = listener.lastTime_ + wakeupDelay_;
305 if (now < lastVSyncTime) {
306 now = lastVSyncTime;
307 }
308
309 now -= referenceTime;
310 int64_t phase = phaseRecord_ + listener.phase_;
311 now -= phase;
312 if (now < 0) {
313 if (vsyncMode_ == VSYNC_MODE_LTPO) {
314 now -= periodRecord_;
315 } else {
316 now = -periodRecord_;
317 }
318 }
319 int64_t numPeriod = now / periodRecord_;
320 int64_t nextTime = (numPeriod + 1) * periodRecord_ + phase;
321 nextTime += referenceTime;
322
323 // 3 / 5 and 1 / 10 are just empirical value
324 int64_t threshold = refreshRateIsChanged_ ? (1 * periodRecord_ / 10) : (3 * periodRecord_ / 5);
325 // between 8000000(8ms) and 8500000(8.5ms)
326 if (!refreshRateIsChanged_ && periodRecord_ > 8000000 && periodRecord_ < 8500000) {
327 threshold = 4 * periodRecord_ / 5; // 4 / 5 is an empirical value
328 }
329 // 3 / 5 just empirical value
330 if (((vsyncMode_ == VSYNC_MODE_LTPS) && (nextTime - listener.lastTime_ < (3 * periodRecord_ / 5))) ||
331 ((vsyncMode_ == VSYNC_MODE_LTPO) && (nextTime - listener.lastTime_ < threshold))) {
332 nextTime += periodRecord_;
333 }
334
335 nextTime -= wakeupDelay_;
336 return nextTime;
337 }
338
GetListenerTimeouted(int64_t now,int64_t occurTimestamp,int64_t referenceTime)339 std::vector<VSyncGenerator::Listener> VSyncGenerator::GetListenerTimeouted(
340 int64_t now, int64_t occurTimestamp, int64_t referenceTime)
341 {
342 std::vector<VSyncGenerator::Listener> ret;
343 for (uint32_t i = 0; i < listeners_.size(); i++) {
344 int64_t t = ComputeListenerNextVSyncTimeStamp(listeners_[i], occurTimestamp, referenceTime);
345 if (t < now || (t - now < errorThreshold)) {
346 listeners_[i].lastTime_ = t;
347 ret.push_back(listeners_[i]);
348 }
349 }
350 return ret;
351 }
352
GetListenerTimeoutedLTPO(int64_t now,int64_t referenceTime)353 std::vector<VSyncGenerator::Listener> VSyncGenerator::GetListenerTimeoutedLTPO(int64_t now, int64_t referenceTime)
354 {
355 std::vector<VSyncGenerator::Listener> ret;
356 for (uint32_t i = 0; i < listeners_.size(); i++) {
357 int64_t t = ComputeListenerNextVSyncTimeStamp(listeners_[i], now, referenceTime);
358 if (t - GetSysTimeNs() < errorThreshold) {
359 listeners_[i].lastTime_ = t;
360 ret.push_back(listeners_[i]);
361 }
362 }
363 refreshRateIsChanged_ = false;
364 return ret;
365 }
366
UpdatePeriodLocked(int64_t period)367 VsyncError VSyncGenerator::UpdatePeriodLocked(int64_t period)
368 {
369 VsyncError ret = VSYNC_ERROR_OK;
370 uint32_t refreshRate = JudgeRefreshRateLocked(period);
371 if ((pendingVsyncMode_ == VSYNC_MODE_LTPO) || (vsyncMode_ == VSYNC_MODE_LTPO)) {
372 if ((refreshRate != 0) && ((currRefreshRate_ == refreshRate) || currRefreshRate_ == 0)) {
373 period_ = period;
374 } else {
375 ScopedBytrace failedTrace("update period failed, refreshRate:" + std::to_string(refreshRate) +
376 ", currRefreshRate_:" + std::to_string(currRefreshRate_));
377 VLOGE("update period failed, refreshRate:%{public}u, currRefreshRate_:%{public}u, period:" VPUBI64,
378 refreshRate, currRefreshRate_, period);
379 ret = VSYNC_ERROR_API_FAILED;
380 }
381 } else {
382 if (period != 0) {
383 period_ = period;
384 } else {
385 ret = VSYNC_ERROR_API_FAILED;
386 }
387 }
388 return ret;
389 }
390
UpdateReferenceTimeLocked(int64_t referenceTime)391 VsyncError VSyncGenerator::UpdateReferenceTimeLocked(int64_t referenceTime)
392 {
393 if ((pendingVsyncMode_ == VSYNC_MODE_LTPO) || (vsyncMode_ == VSYNC_MODE_LTPO)) {
394 referenceTime_ = referenceTime - referenceTimeOffsetPulseNum_ * pulse_;
395 } else {
396 referenceTime_ = referenceTime;
397 }
398 return VSYNC_ERROR_OK;
399 }
400
UpdateMode(int64_t period,int64_t phase,int64_t referenceTime)401 VsyncError VSyncGenerator::UpdateMode(int64_t period, int64_t phase, int64_t referenceTime)
402 {
403 ScopedBytrace func("UpdateMode, period:" + std::to_string(period) +
404 ", phase:" + std::to_string(phase) +
405 ", referenceTime:" + std::to_string((referenceTime)) +
406 ", referenceTimeOffsetPulseNum_:" + std::to_string(referenceTimeOffsetPulseNum_));
407 if (period < 0 || referenceTime < 0) {
408 VLOGE("wrong parameter, period:" VPUBI64 ", referenceTime:" VPUBI64, period, referenceTime);
409 return VSYNC_ERROR_INVALID_ARGUMENTS;
410 }
411 std::lock_guard<std::mutex> locker(mutex_);
412 phase_ = phase;
413 if (period != 0) {
414 UpdatePeriodLocked(period);
415 }
416 UpdateReferenceTimeLocked(referenceTime);
417 startRefresh_ = false;
418 con_.notify_all();
419 return VSYNC_ERROR_OK;
420 }
421
AddListener(int64_t phase,const sptr<OHOS::Rosen::VSyncGenerator::Callback> & cb)422 VsyncError VSyncGenerator::AddListener(int64_t phase, const sptr<OHOS::Rosen::VSyncGenerator::Callback>& cb)
423 {
424 ScopedBytrace func("AddListener");
425 std::lock_guard<std::mutex> locker(mutex_);
426 if (cb == nullptr) {
427 return VSYNC_ERROR_INVALID_ARGUMENTS;
428 }
429 Listener listener;
430 listener.phase_ = phase;
431 listener.callback_ = cb;
432 listener.lastTime_ = GetSysTimeNs() - period_ + phase_;
433
434 listeners_.push_back(listener);
435
436 size_t i = 0;
437 for (; i < listenersRecord_.size(); i++) {
438 if (listener.callback_ == listenersRecord_[i].callback_) {
439 break;
440 }
441 }
442 if (i == listenersRecord_.size()) {
443 listenersRecord_.push_back(listener);
444 }
445 con_.notify_all();
446 waitForTimeoutCon_.notify_all();
447 return VSYNC_ERROR_OK;
448 }
449
JudgeRefreshRateLocked(int64_t period)450 uint32_t VSyncGenerator::JudgeRefreshRateLocked(int64_t period)
451 {
452 if (period <= 0) {
453 return 0;
454 }
455 int32_t actualRefreshRate = round(1.0/((double)period/1000000000.0)); // 1.0s == 1000000000.0ns
456 int32_t refreshRate = actualRefreshRate;
457 int32_t diff = 0;
458 // 在actualRefreshRate附近找一个能被VSYNC_MAX_REFRESHRATE整除的刷新率作为训练pulse的参考刷新率
459 while ((abs(refreshRate - actualRefreshRate) < MAX_REFRESHRATE_DEVIATION) &&
460 (VSYNC_MAX_REFRESHRATE % refreshRate != 0)) {
461 if (diff < 0) {
462 diff = -diff;
463 } else {
464 diff = -diff - 1;
465 }
466 refreshRate = actualRefreshRate + diff;
467 }
468 if (VSYNC_MAX_REFRESHRATE % refreshRate != 0) {
469 VLOGE("Not Support this refresh rate: %{public}d, update pulse failed.", actualRefreshRate);
470 return 0;
471 }
472 pulse_ = period / (VSYNC_MAX_REFRESHRATE / refreshRate);
473 return static_cast<uint32_t>(refreshRate);
474 }
475
ChangeGeneratorRefreshRateModel(const ListenerRefreshRateData & listenerRefreshRates,const ListenerPhaseOffsetData & listenerPhaseOffset,uint32_t generatorRefreshRate)476 VsyncError VSyncGenerator::ChangeGeneratorRefreshRateModel(const ListenerRefreshRateData &listenerRefreshRates,
477 const ListenerPhaseOffsetData &listenerPhaseOffset,
478 uint32_t generatorRefreshRate)
479 {
480 ScopedBytrace func("ChangeGeneratorRefreshRateModel:" + std::to_string(generatorRefreshRate));
481 std::lock_guard<std::mutex> locker(mutex_);
482 if ((vsyncMode_ != VSYNC_MODE_LTPO) && (pendingVsyncMode_ != VSYNC_MODE_LTPO)) {
483 ScopedBytrace trace("it's not ltpo mode.");
484 return VSYNC_ERROR_NOT_SUPPORT;
485 }
486 if (pulse_ == 0) {
487 ScopedBytrace trace("pulse is not ready!!!");
488 VLOGE("pulse is not ready!!!");
489 return VSYNC_ERROR_API_FAILED;
490 }
491 if ((generatorRefreshRate <= 0 || (VSYNC_MAX_REFRESHRATE % generatorRefreshRate != 0))) {
492 ScopedBytrace trace("Not support this refresh rate: " + std::to_string(generatorRefreshRate));
493 VLOGE("Not support this refresh rate: %{public}u", generatorRefreshRate);
494 return VSYNC_ERROR_NOT_SUPPORT;
495 }
496
497 changingRefreshRates_ = listenerRefreshRates;
498 needChangeRefreshRates_ = true;
499
500 changingPhaseOffset_ = listenerPhaseOffset;
501 needChangePhaseOffset_ = true;
502
503 if (generatorRefreshRate != currRefreshRate_) {
504 changingGeneratorRefreshRate_ = generatorRefreshRate;
505 needChangeGeneratorRefreshRate_ = true;
506 }
507
508 waitForTimeoutCon_.notify_all();
509 return VSYNC_ERROR_OK;
510 }
511
GetVSyncPulse()512 int64_t VSyncGenerator::GetVSyncPulse()
513 {
514 std::lock_guard<std::mutex> locker(mutex_);
515 return pulse_;
516 }
517
SetVSyncMode(VSyncMode vsyncMode)518 VsyncError VSyncGenerator::SetVSyncMode(VSyncMode vsyncMode)
519 {
520 ScopedBytrace func("SetVSyncMode:" + std::to_string(vsyncMode));
521 std::lock_guard<std::mutex> locker(mutex_);
522 pendingVsyncMode_ = vsyncMode;
523 return VSYNC_ERROR_OK;
524 }
525
GetVSyncMode()526 VSyncMode VSyncGenerator::GetVSyncMode()
527 {
528 std::lock_guard<std::mutex> locker(mutex_);
529 return vsyncMode_;
530 }
531
SetVSyncPhaseByPulseNum(int32_t phaseByPulseNum)532 VsyncError VSyncGenerator::SetVSyncPhaseByPulseNum(int32_t phaseByPulseNum)
533 {
534 std::lock_guard<std::mutex> locker(mutex_);
535 referenceTimeOffsetPulseNum_ = phaseByPulseNum;
536 defaultReferenceTimeOffsetPulseNum_ = phaseByPulseNum;
537 return VSYNC_ERROR_OK;
538 }
539
SetReferenceTimeOffset(int32_t offsetByPulseNum)540 VsyncError VSyncGenerator::SetReferenceTimeOffset(int32_t offsetByPulseNum)
541 {
542 std::lock_guard<std::mutex> locker(mutex_);
543 referenceTimeOffsetPulseNum_ = offsetByPulseNum;
544 return VSYNC_ERROR_OK;
545 }
546
StartRefresh()547 VsyncError VSyncGenerator::StartRefresh()
548 {
549 std::lock_guard<std::mutex> lock(mutex_);
550 startRefresh_ = true;
551 referenceTimeOffsetPulseNum_ = defaultReferenceTimeOffsetPulseNum_;
552 return VSYNC_ERROR_OK;
553 }
554
CheckAndUpdateRefereceTime(int64_t hardwareVsyncInterval,int64_t referenceTime)555 VsyncError VSyncGenerator::CheckAndUpdateRefereceTime(int64_t hardwareVsyncInterval, int64_t referenceTime)
556 {
557 if (hardwareVsyncInterval < 0 || referenceTime < 0) {
558 VLOGE("wrong parameter, hardwareVsyncInterval:" VPUBI64 ", referenceTime:" VPUBI64,
559 hardwareVsyncInterval, referenceTime);
560 return VSYNC_ERROR_INVALID_ARGUMENTS;
561 }
562 std::lock_guard<std::mutex> locker(mutex_);
563 if (pendingPeriod_ <= 0) {
564 return VSYNC_ERROR_API_FAILED;
565 }
566 if ((abs(pendingReferenceTime_ - referenceTime_) < MAX_TIMESTAMP_THRESHOLD) &&
567 (abs(hardwareVsyncInterval - pendingPeriod_) < MAX_TIMESTAMP_THRESHOLD)) {
568 // framerate has changed
569 frameRateChanging_ = false;
570 pendingPeriod_ = 0;
571 int64_t actualOffset = referenceTime - pendingReferenceTime_;
572 if (pulse_ == 0) {
573 VLOGI("[%{public}s] pulse is not ready.", __func__);
574 return VSYNC_ERROR_API_FAILED;
575 }
576 int32_t actualOffsetPulseNum = round((double)actualOffset/(double)pulse_);
577 if (startRefresh_) {
578 referenceTimeOffsetPulseNum_ = defaultReferenceTimeOffsetPulseNum_;
579 } else {
580 referenceTimeOffsetPulseNum_ = std::max(actualOffsetPulseNum, defaultReferenceTimeOffsetPulseNum_);
581 }
582 ScopedBytrace func("UpdateMode, referenceTime:" + std::to_string((referenceTime)) +
583 ", actualOffsetPulseNum:" + std::to_string((actualOffsetPulseNum)) +
584 ", referenceTimeOffsetPulseNum_:" + std::to_string(referenceTimeOffsetPulseNum_) +
585 ", startRefresh_:" + std::to_string(startRefresh_));
586 UpdateReferenceTimeLocked(referenceTime);
587 startRefresh_ = false;
588 }
589 return VSYNC_ERROR_OK;
590 }
591
RemoveListener(const sptr<OHOS::Rosen::VSyncGenerator::Callback> & cb)592 VsyncError VSyncGenerator::RemoveListener(const sptr<OHOS::Rosen::VSyncGenerator::Callback>& cb)
593 {
594 ScopedBytrace func("RemoveListener");
595 std::lock_guard<std::mutex> locker(mutex_);
596 if (cb == nullptr) {
597 return VSYNC_ERROR_INVALID_ARGUMENTS;
598 }
599 bool removeFlag = false;
600 auto it = listeners_.begin();
601 for (; it < listeners_.end(); it++) {
602 if (it->callback_ == cb) {
603 listeners_.erase(it);
604 removeFlag = true;
605 break;
606 }
607 }
608 if (!removeFlag) {
609 return VSYNC_ERROR_INVALID_ARGUMENTS;
610 }
611 con_.notify_all();
612 return VSYNC_ERROR_OK;
613 }
614
ChangePhaseOffset(const sptr<OHOS::Rosen::VSyncGenerator::Callback> & cb,int64_t offset)615 VsyncError VSyncGenerator::ChangePhaseOffset(const sptr<OHOS::Rosen::VSyncGenerator::Callback>& cb, int64_t offset)
616 {
617 std::lock_guard<std::mutex> locker(mutex_);
618 if (cb == nullptr) {
619 return VSYNC_ERROR_INVALID_ARGUMENTS;
620 }
621 auto it = listeners_.begin();
622 for (; it < listeners_.end(); it++) {
623 if (it->callback_ == cb) {
624 break;
625 }
626 }
627 if (it != listeners_.end()) {
628 it->phase_ = offset;
629 } else {
630 return VSYNC_ERROR_INVALID_OPERATING;
631 }
632 return VSYNC_ERROR_OK;
633 }
634
IsEnable()635 bool VSyncGenerator::IsEnable()
636 {
637 std::lock_guard<std::mutex> locker(mutex_);
638 return period_ > 0;
639 }
640
GetFrameRateChaingStatus()641 bool VSyncGenerator::GetFrameRateChaingStatus()
642 {
643 std::lock_guard<std::mutex> locker(mutex_);
644 return frameRateChanging_;
645 }
646
SetPendingMode(int64_t period,int64_t timestamp)647 void VSyncGenerator::SetPendingMode(int64_t period, int64_t timestamp)
648 {
649 if (period <= 0) {
650 return;
651 }
652 std::lock_guard<std::mutex> lock(mutex_);
653 pendingPeriod_ = period;
654 pendingReferenceTime_ = timestamp;
655 }
656
Dump(std::string & result)657 void VSyncGenerator::Dump(std::string &result)
658 {
659 result.append("\n-- VSyncGenerator --");
660 result += "\nperiod:" + std::to_string(period_);
661 result += "\nphase:" + std::to_string(phase_);
662 result += "\nreferenceTime:" + std::to_string(referenceTime_);
663 result += "\nvsyncMode:" + std::to_string(vsyncMode_);
664 }
665 } // namespace impl
CreateVSyncGenerator()666 sptr<VSyncGenerator> CreateVSyncGenerator()
667 {
668 return impl::VSyncGenerator::GetInstance();
669 }
670
DestroyVSyncGenerator()671 void DestroyVSyncGenerator()
672 {
673 impl::VSyncGenerator::DeleteInstance();
674 }
675 }
676 }
677