1 /*
2 * Copyright (c) 2022-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 <vsync_receiver.h>
17 #include "transaction/rs_interfaces.h"
18 #include "feature/hyper_graphic_manager/rs_frame_rate_linker.h"
19 #include "vsync_log.h"
20 #include "native_vsync.h"
21
22 using namespace OHOS;
23
24 namespace {
25 struct NativeVSync {
26 std::shared_ptr<OHOS::Rosen::VSyncReceiver> receiver_;
27 std::shared_ptr<OHOS::Rosen::RSFrameRateLinker> frameRateLinker_;
28 };
29 }
OH_NativeVSync_OHNativeVSyncToNativeVSync(OH_NativeVSync * ohNativeVSync)30 static NativeVSync* OH_NativeVSync_OHNativeVSyncToNativeVSync(OH_NativeVSync* ohNativeVSync)
31 {
32 return reinterpret_cast<NativeVSync*>(ohNativeVSync);
33 }
34
OH_NativeVSync_NativeVSyncToOHNativeVSync(NativeVSync * nativeVSync)35 static OH_NativeVSync* OH_NativeVSync_NativeVSyncToOHNativeVSync(NativeVSync* nativeVSync)
36 {
37 return reinterpret_cast<OH_NativeVSync*>(nativeVSync);
38 }
39
CreateAndInitVSyncReceiver(const std::string & vsyncName,NativeVSync * nativeVSync,uint64_t windowID=0,bool isAssociatedWindow=false)40 std::shared_ptr<OHOS::Rosen::VSyncReceiver> CreateAndInitVSyncReceiver(
41 const std::string& vsyncName,
42 NativeVSync* nativeVSync,
43 uint64_t windowID = 0,
44 bool isAssociatedWindow = false)
45 {
46 auto& rsClient = OHOS::Rosen::RSInterfaces::GetInstance();
47 std::shared_ptr<OHOS::Rosen::VSyncReceiver> receiver;
48 if (nativeVSync == nullptr || nativeVSync->frameRateLinker_ == nullptr) {
49 return nullptr;
50 }
51 receiver = rsClient.CreateVSyncReceiver(
52 vsyncName, nativeVSync->frameRateLinker_->GetId(), nullptr, windowID, isAssociatedWindow);
53 if (receiver == nullptr) {
54 VLOGE("Create VSyncReceiver failed");
55 return nullptr;
56 }
57 int ret = receiver->Init();
58 if (ret != 0) {
59 VLOGE("VSyncReceiver Init failed, ret:%{public}d", ret);
60 return nullptr;
61 }
62 return receiver;
63 }
64
OH_NativeVSync_Create(const char * name,unsigned int length)65 OH_NativeVSync* OH_NativeVSync_Create(const char* name, unsigned int length)
66 {
67 if (name == nullptr) {
68 VLOGE("name is nullptr, please check");
69 return nullptr;
70 }
71 std::string vsyncName(name, length);
72 NativeVSync* nativeVSync = new NativeVSync;
73 if (nativeVSync == nullptr) {
74 VLOGE("nativeVSync create fail");
75 return nullptr;
76 }
77 nativeVSync->frameRateLinker_ = OHOS::Rosen::RSFrameRateLinker::Create();
78 if (nativeVSync->frameRateLinker_ == nullptr) {
79 VLOGE("frameRateLinker_ create fail");
80 delete nativeVSync;
81 return nullptr;
82 }
83 nativeVSync->frameRateLinker_->SetEnable(true);
84 auto receiver = CreateAndInitVSyncReceiver(vsyncName, nativeVSync);
85 if (receiver == nullptr) {
86 VLOGE("receiver is nullptr, please check");
87 delete nativeVSync;
88 return nullptr;
89 }
90 nativeVSync->receiver_ = receiver;
91 return OH_NativeVSync_NativeVSyncToOHNativeVSync(nativeVSync);
92 }
93
OH_NativeVSync_Create_ForAssociatedWindow(uint64_t windowID,const char * name,unsigned int length)94 OH_NativeVSync* OH_NativeVSync_Create_ForAssociatedWindow(uint64_t windowID, const char* name, unsigned int length)
95 {
96 if (name == nullptr) {
97 VLOGE("name is nullptr, please check");
98 return nullptr;
99 }
100 std::string vsyncName(name, length);
101 NativeVSync* nativeVSync = new NativeVSync;
102 if (nativeVSync == nullptr) {
103 VLOGE("nativeVSync create fail");
104 return nullptr;
105 }
106 nativeVSync->frameRateLinker_ = OHOS::Rosen::RSFrameRateLinker::Create();
107 auto receiver = CreateAndInitVSyncReceiver(vsyncName, nativeVSync, windowID, true);
108 if (receiver == nullptr) {
109 VLOGE("receiver is nullptr, please check");
110 delete nativeVSync;
111 return nullptr;
112 }
113 nativeVSync->receiver_ = receiver;
114 return OH_NativeVSync_NativeVSyncToOHNativeVSync(nativeVSync);
115 }
116
OH_NativeVSync_Destroy(OH_NativeVSync * nativeVSync)117 void OH_NativeVSync_Destroy(OH_NativeVSync *nativeVSync)
118 {
119 if (nativeVSync == nullptr) {
120 VLOGE("parameter is nullptr, please check");
121 return;
122 }
123
124 delete OH_NativeVSync_OHNativeVSyncToNativeVSync(nativeVSync);
125 nativeVSync = nullptr;
126 }
127
OH_NativeVSync_RequestFrame(OH_NativeVSync * ohNativeVSync,OH_NativeVSync_FrameCallback callback,void * data)128 int OH_NativeVSync_RequestFrame(OH_NativeVSync *ohNativeVSync, OH_NativeVSync_FrameCallback callback, void* data)
129 {
130 NativeVSync* nativeVSync = OH_NativeVSync_OHNativeVSyncToNativeVSync(ohNativeVSync);
131 if (nativeVSync == nullptr || nativeVSync->receiver_ == nullptr || callback == nullptr) {
132 VLOGE("parameter is nullptr, please check");
133 return VSYNC_ERROR_INVALID_ARGUMENTS;
134 }
135 OHOS::Rosen::VSyncReceiver::FrameCallback frameCallback = {
136 .userData_ = data,
137 .callback_ = callback,
138 };
139 return nativeVSync->receiver_->RequestNextVSync(frameCallback);
140 }
141
OH_NativeVSync_RequestFrameWithMultiCallback(OH_NativeVSync * ohNativeVSync,OH_NativeVSync_FrameCallback callback,void * data)142 int OH_NativeVSync_RequestFrameWithMultiCallback(
143 OH_NativeVSync *ohNativeVSync, OH_NativeVSync_FrameCallback callback, void* data)
144 {
145 NativeVSync* nativeVSync = OH_NativeVSync_OHNativeVSyncToNativeVSync(ohNativeVSync);
146 if (nativeVSync == nullptr || nativeVSync->receiver_ == nullptr || callback == nullptr) {
147 VLOGE("parameter is nullptr, please check");
148 return VSYNC_ERROR_INVALID_ARGUMENTS;
149 }
150 OHOS::Rosen::VSyncReceiver::FrameCallback frameCallback = {
151 .userData_ = data,
152 .callback_ = callback,
153 };
154 return nativeVSync->receiver_->RequestNextVSyncWithMultiCallback(frameCallback);
155 }
156
OH_NativeVSync_GetPeriod(OH_NativeVSync * nativeVsync,long long * period)157 int OH_NativeVSync_GetPeriod(OH_NativeVSync* nativeVsync, long long* period)
158 {
159 NativeVSync* nativeVSync = OH_NativeVSync_OHNativeVSyncToNativeVSync(nativeVsync);
160 if (nativeVSync == nullptr || nativeVSync->receiver_ == nullptr || period == nullptr) {
161 VLOGE("parameter is nullptr, please check");
162 return VSYNC_ERROR_INVALID_ARGUMENTS;
163 }
164 return nativeVSync->receiver_->GetVSyncPeriod(*reinterpret_cast<int64_t*>(period));
165 }
166
OH_NativeVSync_DVSyncSwitch(OH_NativeVSync * ohNativeVSync,bool enable)167 int OH_NativeVSync_DVSyncSwitch(OH_NativeVSync* ohNativeVSync, bool enable)
168 {
169 NativeVSync* nativeVSync = OH_NativeVSync_OHNativeVSyncToNativeVSync(ohNativeVSync);
170 if (nativeVSync == nullptr || nativeVSync->receiver_ == nullptr) {
171 VLOGE("parameter is nullptr, please check");
172 return VSYNC_ERROR_INVALID_ARGUMENTS;
173 }
174 return nativeVSync->receiver_->SetNativeDVSyncSwitch(enable);
175 }
176
177 namespace {
IsInputRateRangeValid(OH_NativeVSync_ExpectedRateRange * range)178 bool IsInputRateRangeValid(OH_NativeVSync_ExpectedRateRange* range)
179 {
180 if (range == nullptr) {
181 VLOGE("input range is nullptr, please check");
182 return false;
183 }
184 return range->min <= range->expected && range->expected <= range->max &&
185 range->min >= 0 && range->max <= RANGE_MAX_REFRESHRATE;
186 }
187 }
188
OH_NativeVSync_SetExpectedFrameRateRange(OH_NativeVSync * nativeVsync,OH_NativeVSync_ExpectedRateRange * range)189 int OH_NativeVSync_SetExpectedFrameRateRange(OH_NativeVSync* nativeVsync, OH_NativeVSync_ExpectedRateRange* range)
190 {
191 NativeVSync* nativeVSync = OH_NativeVSync_OHNativeVSyncToNativeVSync(nativeVsync);
192 if (nativeVSync == nullptr || range == nullptr) {
193 VLOGE("parameter is nullptr, please check");
194 return VSYNC_ERROR_INVALID_ARGUMENTS;
195 }
196 if (!IsInputRateRangeValid(range)) {
197 VLOGE("ExpectedRateRange Error, please check.");
198 return VSYNC_ERROR_INVALID_ARGUMENTS;
199 }
200 if (nativeVSync->frameRateLinker_ == nullptr) {
201 VLOGE("FrameRateLinker is nullptr, please check.");
202 return VSYNC_ERROR_NOT_SUPPORT;
203 }
204 OHOS::Rosen::FrameRateRange frameRateRange(range->min, range->max, range->expected,
205 OHOS::Rosen::NATIVE_VSYNC_FRAME_RATE_TYPE);
206 VLOGI("NativeVsyncExpectedRateRange:{%{public}d, %{public}d, %{public}d}",
207 range->min, range->max, range->expected);
208 if (nativeVSync->frameRateLinker_->IsEnable()) {
209 nativeVSync->frameRateLinker_->UpdateFrameRateRangeImme(frameRateRange);
210 }
211 return VSYNC_ERROR_OK;
212 }
213