• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &param);
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