1 /*
2  * Copyright (c) 2022 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 "sorft_vsync.h"
17 #include <chrono>
18 #include <sys/time.h>
19 #include "display_common.h"
20 
21 namespace OHOS {
22 namespace HDI {
23 namespace DISPLAY {
SorftVsync()24 SorftVsync::SorftVsync() {}
25 
Init()26 int32_t SorftVsync::Init()
27 {
28     thread_ = std::make_unique<std::thread>([this]() { WorkThread(); });
29     DISPLAY_CHK_RETURN((thread_ == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not create thread"));
30     running_ = true;
31     return DISPLAY_SUCCESS;
32 }
33 
GetInstance()34 SorftVsync &SorftVsync::GetInstance()
35 {
36     static SorftVsync instance;
37     static std::once_flag once;
38     std::call_once(once, [&]() {
39         int ret = instance.Init();
40         if (ret != DISPLAY_SUCCESS) {
41             DISPLAY_LOGE("Vsync Worker Init failed");
42         }
43     });
44     return instance;
45 }
46 
~SorftVsync()47 SorftVsync::~SorftVsync()
48 {
49     DISPLAY_LOGD();
50     {
51         std::lock_guard<std::mutex> lg(mutext_);
52         running_ = false;
53     }
54     condition_.notify_one();
55     if (thread_ != nullptr) {
56         thread_->join();
57     }
58 }
59 
CheckRuning()60 bool SorftVsync::CheckRuning()
61 {
62     std::unique_lock<std::mutex> ul(mutext_);
63     condition_.wait(ul, [this]() { return (enable_ || !running_); });
64     return running_;
65 }
66 
EnableVsync(bool enable)67 void SorftVsync::EnableVsync(bool enable)
68 {
69     DISPLAY_LOGD();
70     {
71         std::lock_guard<std::mutex> lg(mutext_);
72         enable_ = enable;
73     }
74     condition_.notify_one();
75 }
76 
WorkThread()77 void SorftVsync::WorkThread()
78 {
79     DISPLAY_LOGD();
80     unsigned int seq = 0;
81     const int SIXTY_HZ_OF_TIME = 16666;
82     struct timespec ts;
83     while (CheckRuning()) {
84         // wait the vblank
85         usleep(SIXTY_HZ_OF_TIME);
86         seq++;
87         if (callback_ != nullptr) {
88             clock_gettime(CLOCK_MONOTONIC, &ts);
89             uint64_t time = ts.tv_nsec;
90             callback_->Vsync(seq, time);
91         } else {
92             DISPLAY_LOGE("the callbac is nullptr");
93         }
94     }
95 }
96 
ReqesterVBlankCb(const std::shared_ptr<VsyncCallBack> & cb)97 void SorftVsync::ReqesterVBlankCb(const std::shared_ptr<VsyncCallBack> &cb)
98 {
99     DISPLAY_LOGD();
100     DISPLAY_CHK_RETURN_NOT_VALUE((cb == nullptr), DISPLAY_LOGE("the VBlankCallback is nullptr "));
101     callback_ = cb;
102 }
103 } // namespace OHOS
104 } // namespace HDI
105 } // namespace DISPLAY
106