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