• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 #include "core/pipeline/pipeline_base.h"
16 #include "core/components_ng/manager/display_sync/ui_display_sync.h"
17 #ifdef ENABLE_ROSEN_BACKEND
18 #include "transaction/rs_interfaces.h"
19 #endif
20 
21 namespace OHOS::Ace {
CheckRate(int32_t vsyncRate,int32_t refreshRateMode)22 void UIDisplaySync::CheckRate(int32_t vsyncRate, int32_t refreshRateMode)
23 {
24     SetVsyncRate(vsyncRate);
25     SetRefreshRateMode(refreshRateMode);
26 
27     CHECK_NULL_VOID(data_);
28     CHECK_NULL_VOID(data_->rate_);
29     CHECK_NULL_VOID(data_->rateRange_);
30     drawFPS_ = FindMatchedRefreshRate(vsyncRate, data_->rateRange_->preferred_);
31     if (drawFPS_ < data_->rateRange_->min_ ||
32         drawFPS_ > data_->rateRange_->max_) {
33         drawFPS_ = SearchMatchedRate(vsyncRate);
34     }
35 
36     if (drawFPS_ == 0) {
37         return;
38     }
39 
40     int32_t curRate = vsyncRate / drawFPS_;
41     if (data_->rate_ != curRate) {
42         data_->rate_ = curRate;
43         rateChanged_ = true;
44         ACE_SCOPED_TRACE("[%s] Id[%" PRIu64 "] RateChangedTo: %d", __func__, GetId(), data_->rate_);
45     }
46     return;
47 }
48 
UpdateData(int64_t nanoTimestamp,int32_t vsyncPeriod)49 void UIDisplaySync::UpdateData(int64_t nanoTimestamp, int32_t vsyncPeriod)
50 {
51     SetTimestampData(nanoTimestamp);
52     int64_t targetTimestamp = nanoTimestamp + static_cast<int64_t>(vsyncPeriod * data_->rate_);
53     SetTargetTimestampData(targetTimestamp);
54 }
55 
JudgeWhetherSkip()56 void UIDisplaySync::JudgeWhetherSkip()
57 {
58     if (rateChanged_) {
59         data_->count_ = 0;
60         rateChanged_ = false;
61     }
62 
63     if (data_->count_ == 0) {
64         data_->noSkip_ = true;
65     } else {
66         data_->noSkip_ = false;
67     }
68 
69     if (data_->rate_ && (data_->rate_ - data_->count_) == 1) {
70         data_->count_ = -1;
71     }
72     data_->count_++;
73 }
74 
OnFrame()75 void UIDisplaySync::OnFrame()
76 {
77     ACE_SCOPED_TRACE("DisplaySyncId[%" PRIu64 "] Type[%d] Timestamp[%" PRIu64 "] TargetTimestamp[%" PRIu64 "]"
78                      "FrameRateRange[%d, %d, %d] DrawFPS[%d] VSyncRate[%d] Rate[%d] noSkip[%d]",
79                      GetId(), static_cast<int32_t>(uiObjectType_), data_->timestamp_, data_->targetTimestamp_,
80                      data_->rateRange_->min_, data_->rateRange_->max_, data_->rateRange_->preferred_,
81                      drawFPS_, sourceVsyncRate_, data_->rate_, data_->noSkip_);
82     TAG_LOGD(AceLogTag::ACE_DISPLAY_SYNC, "Id[%{public}" PRIu64 "] Type[%{public}d] FrameRateRange[%{public}d, "
83         "%{public}d, %{public}d], DrawFPS[%{public}d] VSyncRate[%{public}d] Rate[%{public}d] noSkip[%{public}d]",
84         GetId(), static_cast<int32_t>(uiObjectType_), data_->rateRange_->min_, data_->rateRange_->max_,
85         data_->rateRange_->preferred_, drawFPS_, sourceVsyncRate_, data_->rate_, data_->noSkip_);
86     if (data_->noSkip_ && data_->onFrame_) {
87         data_->onFrame_();
88     }
89 
90     // Callback from JS_DisplaySync and Native_XComponent
91     if (data_->noSkip_ && data_->onFrameWithData_) {
92         data_->onFrameWithData_(data_);
93     }
94 
95     // Callback from Animator
96     if (data_->noSkip_ && data_->onFrameWithTimestamp_) {
97         data_->onFrameWithTimestamp_(data_->timestamp_);
98     }
99 
100     JudgeWhetherRequestFrame();
101 }
102 
AddToPipeline(WeakPtr<PipelineBase> & pipelineContext)103 void UIDisplaySync::AddToPipeline(WeakPtr<PipelineBase>& pipelineContext)
104 {
105     if (GetCurrentContext()) {
106         TAG_LOGD(AceLogTag::ACE_DISPLAY_SYNC, "[DisplaySync] existed in Pipeline.");
107         return;
108     }
109 
110     auto context = pipelineContext.Upgrade();
111     if (!context) {
112         context = PipelineBase::GetCurrentContextSafelyWithCheck();
113         if (!context) {
114             TAG_LOGE(AceLogTag::ACE_DISPLAY_SYNC, "[DisplaySync] AddToPipeline CurrentContext is nullptr.");
115             return;
116         }
117         TAG_LOGD(AceLogTag::ACE_DISPLAY_SYNC, "[DisplaySync] Add to current context safely.");
118     }
119 
120     context_ = context;
121     RefPtr<UIDisplaySyncManager> dsm = context->GetOrCreateUIDisplaySyncManager();
122     if (!dsm) {
123         return;
124     }
125     dsm->AddDisplaySync(AceType::Claim(this));
126 }
127 
DelFromPipeline(WeakPtr<PipelineBase> & pipelineContext)128 void UIDisplaySync::DelFromPipeline(WeakPtr<PipelineBase>& pipelineContext)
129 {
130     auto context = GetCurrentContext();
131     if (!context) {
132         TAG_LOGE(AceLogTag::ACE_DISPLAY_SYNC, "[DisplaySync] DelFromPipeline CurrentContext is nullptr.");
133         return;
134     }
135 
136     RefPtr<UIDisplaySyncManager> dsm = context->GetOrCreateUIDisplaySyncManager();
137     if (!dsm) {
138         TAG_LOGE(AceLogTag::ACE_DISPLAY_SYNC, "[DisplaySync] DSM is nullptr.");
139         return;
140     }
141     dsm->RemoveDisplaySync(AceType::Claim(this));
142     context_ = nullptr;
143 }
144 
IsAddToPipeline(WeakPtr<PipelineBase> & pipelineContext)145 bool UIDisplaySync::IsAddToPipeline(WeakPtr<PipelineBase>& pipelineContext)
146 {
147     auto context = GetCurrentContext();
148     if (!context) {
149         return false;
150     }
151 
152     RefPtr<UIDisplaySyncManager> dsm = context->GetOrCreateUIDisplaySyncManager();
153     if (!dsm) {
154         return false;
155     }
156     return dsm->HasDisplaySync(AceType::Claim(this));
157 }
158 
AddToPipelineOnContainer()159 void UIDisplaySync::AddToPipelineOnContainer()
160 {
161     WeakPtr<PipelineBase> pipeline = PipelineBase::GetCurrentContext();
162     AddToPipeline(pipeline);
163     return;
164 }
165 
DelFromPipelineOnContainer()166 void UIDisplaySync::DelFromPipelineOnContainer()
167 {
168     WeakPtr<PipelineBase> pipeline = PipelineBase::GetCurrentContext();
169     DelFromPipeline(pipeline);
170     return;
171 }
172 
IsOnPipeline()173 bool UIDisplaySync::IsOnPipeline()
174 {
175     WeakPtr<PipelineBase> pipeline = PipelineBase::GetCurrentContext();
176     return IsAddToPipeline(pipeline);
177 }
178 
RequestFrame()179 void UIDisplaySync::RequestFrame()
180 {
181     auto context = GetCurrentContext();
182     if (!context) {
183         return;
184     }
185     context->RequestFrame();
186 }
187 
JudgeWhetherRequestFrame()188 void UIDisplaySync::JudgeWhetherRequestFrame()
189 {
190     bool isNeedRequest = data_->onFrame_ || data_->onFrameWithData_ || data_->onFrameWithTimestamp_;
191     if (isNeedRequest) {
192         RequestFrame();
193     }
194 }
195 
RegisterOnFrame(OnFrameCallBack && onFrameCallBack)196 void UIDisplaySync::RegisterOnFrame(OnFrameCallBack&& onFrameCallBack)
197 {
198     data_->onFrame_ = std::move(onFrameCallBack);
199 }
200 
RegisterOnFrameWithData(OnFrameCallBackWithData && onFrameCallBack)201 void UIDisplaySync::RegisterOnFrameWithData(OnFrameCallBackWithData&& onFrameCallBack)
202 {
203     data_->onFrameWithData_ = std::move(onFrameCallBack);
204 }
205 
RegisterOnFrameWithTimestamp(OnFrameCallBackWithTimestamp && onFrameCallBack)206 void UIDisplaySync::RegisterOnFrameWithTimestamp(OnFrameCallBackWithTimestamp&& onFrameCallBack)
207 {
208     data_->onFrameWithTimestamp_ = std::move(onFrameCallBack);
209 }
210 
UnregisterOnFrame()211 void UIDisplaySync::UnregisterOnFrame()
212 {
213     data_->onFrame_ = nullptr;
214     data_->onFrameWithData_ = nullptr;
215     data_->onFrameWithTimestamp_ = nullptr;
216 }
217 
SetTimestampData(int64_t timestamp)218 void UIDisplaySync::SetTimestampData(int64_t timestamp)
219 {
220     data_->SetTimestamp(timestamp);
221 }
222 
GetTimestampData() const223 int64_t UIDisplaySync::GetTimestampData() const
224 {
225     return data_->GetTimestamp();
226 }
227 
SetTargetTimestampData(int64_t targetTimestamp)228 void UIDisplaySync::SetTargetTimestampData(int64_t targetTimestamp)
229 {
230     data_->SetTargetTimestamp(targetTimestamp);
231 }
232 
GetTargetTimestampData() const233 int64_t UIDisplaySync::GetTargetTimestampData() const
234 {
235     return data_->GetTargetTimestamp();
236 }
237 
SetRefreshRateMode(int32_t refreshRateMode)238 void UIDisplaySync::SetRefreshRateMode(int32_t refreshRateMode)
239 {
240     refreshRateMode_ = refreshRateMode;
241 }
242 
GetRefreshRateMode() const243 int32_t UIDisplaySync::GetRefreshRateMode() const
244 {
245     return refreshRateMode_;
246 }
247 
IsAutoRefreshRateMode() const248 bool UIDisplaySync::IsAutoRefreshRateMode() const
249 {
250     return refreshRateMode_ == static_cast<int32_t>(RefreshRateMode::REFRESHRATE_MODE_AUTO);
251 }
252 
IsNonAutoRefreshRateMode() const253 bool UIDisplaySync::IsNonAutoRefreshRateMode() const
254 {
255     return refreshRateMode_ != static_cast<int32_t>(RefreshRateMode::REFRESHRATE_MODE_AUTO);
256 }
257 
FindRefreshRateFactors(int32_t refreshRate)258 std::vector<int32_t> UIDisplaySync::FindRefreshRateFactors(int32_t refreshRate)
259 {
260     std::vector<int32_t> refreshRateFactors;
261     for (int32_t i = 1; i * i <= refreshRate; ++i) {
262         if (refreshRate % i == 0) {
263             refreshRateFactors.emplace_back(i);
264             if (i != refreshRate / i) {
265                 refreshRateFactors.emplace_back(refreshRate / i);
266             }
267         }
268     }
269     sort(refreshRateFactors.begin(), refreshRateFactors.end());
270     return refreshRateFactors;
271 }
272 
FindMatchedRefreshRate(int32_t vsyncRate,int32_t targetRate)273 int32_t UIDisplaySync::FindMatchedRefreshRate(int32_t vsyncRate, int32_t targetRate)
274 {
275     if (targetRate == 0 || targetRate > vsyncRate) {
276         return vsyncRate;
277     }
278 
279     if (IsCommonDivisor(targetRate, vsyncRate)) {
280         return targetRate;
281     }
282 
283     if (!refreshRateToFactorsMap_.count(vsyncRate)) {
284         refreshRateToFactorsMap_[vsyncRate] = FindRefreshRateFactors(vsyncRate);
285     }
286 
287     std::vector<int32_t> refreshRateFactors = refreshRateToFactorsMap_[vsyncRate];
288     if (refreshRateFactors.empty()) {
289         return 0;
290     }
291     auto it = std::lower_bound(refreshRateFactors.begin(), refreshRateFactors.end(), targetRate);
292     if (it == refreshRateFactors.begin()) {
293         return *it;
294     } else if (it == refreshRateFactors.end()) {
295         return *(it - 1);
296     }
297     return std::abs(*it - targetRate) < std::abs(*(it - 1) - targetRate) ? *it : *(it - 1);
298 }
299 
SearchMatchedRate(int32_t vsyncRate,int32_t iterCount)300 int32_t UIDisplaySync::SearchMatchedRate(int32_t vsyncRate, int32_t iterCount)
301 {
302     if (vsyncRate != 0 && iterCount >= vsyncRate) {
303         return FindMatchedRefreshRate(vsyncRate, data_->rateRange_->preferred_);
304     }
305 
306     if (iterCount == 0 || vsyncRate == 0) {
307         return vsyncRate;
308     }
309 
310     int32_t expectedRate = vsyncRate / iterCount;
311     if (data_->rateRange_->min_ <= expectedRate &&
312         data_->rateRange_->max_ >= expectedRate) {
313         return FindMatchedRefreshRate(vsyncRate, expectedRate);
314     }
315 
316     return SearchMatchedRate(vsyncRate, ++iterCount);
317 }
318 
GetCurrentContext()319 RefPtr<PipelineBase> UIDisplaySync::GetCurrentContext()
320 {
321     auto context = context_.Upgrade();
322     return context;
323 }
324 
UIDisplaySync(UIObjectType uiObjectType)325 UIDisplaySync::UIDisplaySync(UIObjectType uiObjectType)
326     : uiObjectType_(uiObjectType)
327 {
328     TAG_LOGD(AceLogTag::ACE_DISPLAY_SYNC, "Create UIDisplaySync, Type: %{public}d",
329         static_cast<int32_t>(uiObjectType_));
330 }
331 
UIDisplaySync()332 UIDisplaySync::UIDisplaySync() {}
333 
~UIDisplaySync()334 UIDisplaySync::~UIDisplaySync() noexcept {}
335 
SetExpectedFrameRateRange(const FrameRateRange & range)336 void UIDisplaySync::SetExpectedFrameRateRange(const FrameRateRange& range)
337 {
338     data_->rateRange_->Set(range.min_, range.max_, range.preferred_);
339 }
340 
SetVsyncRate(int32_t vsyncRate)341 bool UIDisplaySync::SetVsyncRate(int32_t vsyncRate)
342 {
343     if (sourceVsyncRate_ == vsyncRate) {
344         return false;
345     }
346     sourceVsyncRate_ = vsyncRate;
347     return true;
348 }
349 
GetDisplaySyncData() const350 RefPtr<DisplaySyncData> UIDisplaySync::GetDisplaySyncData() const
351 {
352     return data_;
353 }
354 
GetAnimatorExpectedRate()355 int32_t UIDisplaySync::GetAnimatorExpectedRate()
356 {
357     // Callback from Animator
358     if (data_ && data_->onFrameWithTimestamp_ == nullptr &&
359         uiObjectType_ != UIObjectType::DISPLAYSYNC_ANIMATOR) {
360         return INVALID_ANIMATOR_EXPECTED_RATE;
361     }
362 
363     int32_t animatorExpectedRate = 0;
364     if (data_ && data_->rateRange_) {
365         animatorExpectedRate = data_->rateRange_->preferred_;
366     }
367     return animatorExpectedRate;
368 }
369 
IsCommonDivisor(int32_t expectedRate,int32_t vsyncRate)370 bool UIDisplaySync::IsCommonDivisor(int32_t expectedRate, int32_t vsyncRate)
371 {
372     if (expectedRate == 0 || vsyncRate == 0) {
373         return false;
374     }
375 
376     int32_t n = vsyncRate / expectedRate;
377     if (expectedRate * n == vsyncRate) {
378         return true;
379     }
380     return false;
381 }
382 
~UIXComponentDisplaySync()383 UIXComponentDisplaySync::~UIXComponentDisplaySync()
384 {
385     if (lastFrameRateRange_.has_value()) {
386         // -1 : means destroy
387         NotifyXComponentExpectedFrameRate(lastId_, -1);
388     }
389 }
390 
NotifyXComponentExpectedFrameRate(const std::string & id)391 void UIXComponentDisplaySync::NotifyXComponentExpectedFrameRate(const std::string& id)
392 {
393     if (lastFrameRateRange_.has_value()) {
394         NotifyXComponentExpectedFrameRate(id, lastFrameRateRange_->preferred_);
395     }
396 }
397 
NotifyXComponentExpectedFrameRate(const std::string & id,int32_t preferred)398 void UIXComponentDisplaySync::NotifyXComponentExpectedFrameRate(const std::string& id, int32_t preferred)
399 {
400     lastId_ = id;
401     if (lastFrameRateRange_.has_value()) {
402 #ifdef ENABLE_ROSEN_BACKEND
403         Rosen::RSInterfaces::GetInstance().NotifyXComponentExpectedFrameRate(lastId_, preferred);
404 #endif
405     }
406 }
407 
NotifyXComponentExpectedFrameRate(const std::string & id,bool isOnTree,const FrameRateRange & expectedFrameRate)408 void UIXComponentDisplaySync::NotifyXComponentExpectedFrameRate(
409     const std::string& id, bool isOnTree, const FrameRateRange& expectedFrameRate)
410 {
411     SetExpectedFrameRateRange(expectedFrameRate);
412     TAG_LOGD(AceLogTag::ACE_DISPLAY_SYNC, "Id: %{public}" PRIu64 " SetExpectedFrameRateRange"
413         "{%{public}d, %{public}d, %{public}d}", GetId(),
414         expectedFrameRate.min_, expectedFrameRate.max_, expectedFrameRate.preferred_);
415     if (expectedFrameRate.preferred_ < 0 ||
416         (lastFrameRateRange_.has_value() && lastFrameRateRange_->preferred_ == expectedFrameRate.preferred_)) {
417         return;
418     }
419     lastFrameRateRange_.emplace(expectedFrameRate.min_, expectedFrameRate.max_, expectedFrameRate.preferred_);
420     if (isOnTree) {
421         NotifyXComponentExpectedFrameRate(id);
422     }
423 }
424 
425 } // namespace OHOS::Ace
426