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_distributor.h"
17 #include <chrono>
18 #include <condition_variable>
19 #include <algorithm>
20 #include <cstdint>
21 #include <mutex>
22 #include <sched.h>
23 #include <sys/resource.h>
24 #include <scoped_bytrace.h>
25 #include <hitrace_meter.h>
26 #include "vsync_log.h"
27 #include "vsync_type.h"
28 #include "vsync_generator.h"
29 #include <rs_trace.h>
30 #include "scoped_trace_fmt.h"
31
32 #ifdef COMPOSER_SCHED_ENABLE
33 #include "if_system_ability_manager.h"
34 #include <iservice_registry.h>
35 #include "system_ability_definition.h"
36 #endif
37
38 namespace OHOS {
39 namespace Rosen {
40 namespace {
41 constexpr int32_t SOFT_VSYNC_PERIOD = 16;
42 constexpr int32_t ERRNO_EAGAIN = -1;
43 constexpr int32_t ERRNO_OTHER = -2;
44 constexpr int32_t THREAD_PRIORTY = -6;
45 constexpr int32_t SCHED_PRIORITY = 2;
46 constexpr int32_t DEFAULT_VSYNC_RATE = 1;
47 constexpr uint32_t SOCKET_CHANNEL_SIZE = 1024;
48 constexpr int32_t VSYNC_CONNECTION_MAX_SIZE = 256;
49 }
50
VSyncConnectionDeathRecipient( wptr<VSyncConnection> conn)51 VSyncConnection::VSyncConnectionDeathRecipient::VSyncConnectionDeathRecipient(
52 wptr<VSyncConnection> conn) : conn_(conn)
53 {
54 }
55
OnRemoteDied(const wptr<IRemoteObject>& token)56 void VSyncConnection::VSyncConnectionDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& token)
57 {
58 auto tokenSptr = token.promote();
59 if (tokenSptr == nullptr) {
60 VLOGW("%{public}s: can't promote remote object.", __func__);
61 return;
62 }
63 auto vsyncConn = conn_.promote();
64 if (vsyncConn == nullptr) {
65 VLOGW("%{public}s: VSyncConnection was dead, do nothing.", __func__);
66 return;
67 }
68 if (vsyncConn->token_ != tokenSptr) {
69 VLOGI("%{public}s: token doesn't match, ignore it.", __func__);
70 return;
71 }
72 VLOGD("%{public}s: clear socketPair, conn name:%{public}s.", __func__, vsyncConn->info_.name_.c_str());
73 VsyncError ret = vsyncConn->Destroy();
74 if (ret != VSYNC_ERROR_OK) {
75 VLOGE("vsync connection clearAll failed!");
76 }
77 }
78
VSyncConnection( const sptr<VSyncDistributor>& distributor, std::string name, const sptr<IRemoteObject>& token, uint64_t id, uint64_t windowNodeId)79 VSyncConnection::VSyncConnection(
80 const sptr<VSyncDistributor>& distributor,
81 std::string name,
82 const sptr<IRemoteObject>& token,
83 uint64_t id,
84 uint64_t windowNodeId)
85 : rate_(-1),
86 info_(name),
87 id_(id),
88 windowNodeId_(windowNodeId),
89 vsyncConnDeathRecipient_(new VSyncConnectionDeathRecipient(this)),
90 token_(token),
91 distributor_(distributor)
92 {
93 socketPair_ = new LocalSocketPair();
94 int32_t err = socketPair_->CreateChannel(SOCKET_CHANNEL_SIZE, SOCKET_CHANNEL_SIZE);
95 if (err != 0) {
96 RS_TRACE_NAME_FMT("Create socket channel failed, errno = %d", errno);
97 }
98 if (token_ != nullptr) {
99 token_->AddDeathRecipient(vsyncConnDeathRecipient_);
100 }
101 proxyPid_ = GetCallingPid();
102 isDead_ = false;
103 }
104
~VSyncConnection()105 VSyncConnection::~VSyncConnection()
106 {
107 if ((token_ != nullptr) && (vsyncConnDeathRecipient_ != nullptr)) {
108 token_->RemoveDeathRecipient(vsyncConnDeathRecipient_);
109 }
110 }
111
RequestNextVSync()112 VsyncError VSyncConnection::RequestNextVSync()
113 {
114 static const std::string DEFAULT_REQUEST = "unknown";
115 return RequestNextVSync(DEFAULT_REQUEST, 0);
116 }
117
RequestNextVSync(const std::string &fromWhom, int64_t lastVSyncTS)118 VsyncError VSyncConnection::RequestNextVSync(const std::string &fromWhom, int64_t lastVSyncTS)
119 {
120 sptr<VSyncDistributor> distributor;
121 {
122 std::unique_lock<std::mutex> locker(mutex_);
123 if (isDead_) {
124 VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
125 return VSYNC_ERROR_API_FAILED;
126 }
127 if (distributor_ == nullptr) {
128 return VSYNC_ERROR_NULLPTR;
129 }
130 distributor = distributor_.promote();
131 if (distributor == nullptr) {
132 return VSYNC_ERROR_NULLPTR;
133 }
134 if (isFirstRequestVsync_) {
135 isFirstRequestVsync_ = false;
136 VLOGI("First vsync is requested, name: %{public}s", info_.name_.c_str());
137 }
138 }
139 return distributor->RequestNextVSync(this, fromWhom, lastVSyncTS);
140 }
141
GetReceiveFd(int32_t &fd)142 VsyncError VSyncConnection::GetReceiveFd(int32_t &fd)
143 {
144 std::unique_lock<std::mutex> locker(mutex_);
145 if (isDead_ || socketPair_ == nullptr) {
146 VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
147 return VSYNC_ERROR_API_FAILED;
148 }
149 fd = socketPair_->GetReceiveDataFd();
150 if (fd < 0) {
151 VLOGE("%{public}s socketPair invalid fd:%{public}d.", __func__, fd);
152 return VSYNC_ERROR_API_FAILED;
153 }
154 return VSYNC_ERROR_OK;
155 }
156
PostEvent(int64_t now, int64_t period, int64_t vsyncCount)157 int32_t VSyncConnection::PostEvent(int64_t now, int64_t period, int64_t vsyncCount)
158 {
159 sptr<LocalSocketPair> socketPair;
160 {
161 std::unique_lock<std::mutex> locker(mutex_);
162 if (isDead_) {
163 RS_TRACE_NAME_FMT("Vsync Client Connection is dead, conn: %s", info_.name_.c_str());
164 VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
165 return ERRNO_OTHER;
166 }
167 socketPair = socketPair_;
168 }
169 if (socketPair == nullptr) {
170 RS_TRACE_NAME_FMT("socketPair is null, conn: %s", info_.name_.c_str());
171 return ERRNO_OTHER;
172 }
173 RS_TRACE_NAME_FMT("SendVsyncTo conn: %s, now:%ld, refreshRate:%d", info_.name_.c_str(), now, refreshRate_);
174 // 3 is array size.
175 int64_t data[3];
176 data[0] = now;
177 // 1, 2: index of array data.
178 data[1] = period;
179 data[2] = vsyncCount;
180 if (isFirstSendVsync_) {
181 isFirstSendVsync_ = false;
182 VLOGI("First vsync has send to : %{public}s", info_.name_.c_str());
183 }
184 int32_t ret = socketPair->SendData(data, sizeof(data));
185 if (ret == ERRNO_EAGAIN) {
186 RS_TRACE_NAME("remove the earlies data and SendData again.");
187 VLOGW("vsync signal is not processed in time, please check pid:%{public}d", proxyPid_);
188 int64_t receiveData[3];
189 socketPair->ReceiveData(receiveData, sizeof(receiveData));
190 ret = socketPair->SendData(data, sizeof(data));
191 }
192 if (ret > -1) {
193 ScopedDebugTrace successful("successful");
194 info_.postVSyncCount_++;
195 if (gcNotifyTask_ != nullptr) {
196 gcNotifyTask_(false);
197 }
198 } else {
199 ScopedBytrace failed("failed");
200 }
201 return ret;
202 }
203
SetVSyncRate(int32_t rate)204 VsyncError VSyncConnection::SetVSyncRate(int32_t rate)
205 {
206 std::unique_lock<std::mutex> locker(mutex_);
207 if (isDead_) {
208 VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
209 return VSYNC_ERROR_API_FAILED;
210 }
211 if (distributor_ == nullptr) {
212 return VSYNC_ERROR_NULLPTR;
213 }
214 const sptr<VSyncDistributor> distributor = distributor_.promote();
215 if (distributor == nullptr) {
216 return VSYNC_ERROR_NULLPTR;
217 }
218 return distributor->SetVSyncRate(rate, this);
219 }
220
CleanAllLocked()221 VsyncError VSyncConnection::CleanAllLocked()
222 {
223 socketPair_ = nullptr;
224 const sptr<VSyncDistributor> distributor = distributor_.promote();
225 if (distributor == nullptr) {
226 return VSYNC_ERROR_OK;
227 }
228 VsyncError ret = distributor->RemoveConnection(this);
229 isDead_ = true;
230 return ret;
231 }
232
Destroy()233 VsyncError VSyncConnection::Destroy()
234 {
235 std::unique_lock<std::mutex> locker(mutex_);
236 return CleanAllLocked();
237 }
238
SetUiDvsyncSwitch(bool dvsyncSwitch)239 VsyncError VSyncConnection::SetUiDvsyncSwitch(bool dvsyncSwitch)
240 {
241 sptr<VSyncDistributor> distributor;
242 {
243 std::unique_lock<std::mutex> locker(mutex_);
244 if (isDead_) {
245 VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
246 return VSYNC_ERROR_API_FAILED;
247 }
248 if (distributor_ == nullptr) {
249 return VSYNC_ERROR_NULLPTR;
250 }
251 distributor = distributor_.promote();
252 if (distributor == nullptr) {
253 return VSYNC_ERROR_NULLPTR;
254 }
255 }
256 return distributor->SetUiDvsyncSwitch(dvsyncSwitch, this);
257 }
258
SetNativeDVSyncSwitch(bool dvsyncSwitch)259 VsyncError VSyncConnection::SetNativeDVSyncSwitch(bool dvsyncSwitch)
260 {
261 sptr<VSyncDistributor> distributor;
262 {
263 std::unique_lock<std::mutex> locker(mutex_);
264 if (isDead_) {
265 VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
266 return VSYNC_ERROR_API_FAILED;
267 }
268 if (distributor_ == nullptr) {
269 return VSYNC_ERROR_NULLPTR;
270 }
271 distributor = distributor_.promote();
272 if (distributor == nullptr) {
273 return VSYNC_ERROR_NULLPTR;
274 }
275 }
276 return distributor->SetNativeDVSyncSwitch(dvsyncSwitch, this);
277 }
278
SetUiDvsyncConfig(int32_t bufferCount)279 VsyncError VSyncConnection::SetUiDvsyncConfig(int32_t bufferCount)
280 {
281 sptr<VSyncDistributor> distributor;
282 {
283 std::unique_lock<std::mutex> locker(mutex_);
284 if (isDead_) {
285 VLOGE("%{public}s VSync Client Connection is dead, name:%{public}s.", __func__, info_.name_.c_str());
286 return VSYNC_ERROR_API_FAILED;
287 }
288 if (distributor_ == nullptr) {
289 return VSYNC_ERROR_NULLPTR;
290 }
291 distributor = distributor_.promote();
292 if (distributor == nullptr) {
293 return VSYNC_ERROR_NULLPTR;
294 }
295 }
296 return distributor->SetUiDvsyncConfig(bufferCount);
297 }
298
VSyncDistributor(sptr<VSyncController> controller, std::string name)299 VSyncDistributor::VSyncDistributor(sptr<VSyncController> controller, std::string name)
300 : controller_(controller), mutex_(), con_(), connections_(),
301 event_(), vsyncEnabled_(false), name_(name)
302 {
303 static const std::string DEFAULT_RS_NAME = "rs";
304 if (name == DEFAULT_RS_NAME) {
305 isRs_ = true;
306 }
307 #if defined(RS_ENABLE_DVSYNC)
308 dvsync_ = new DVsync(isRs_);
309 if (dvsync_->IsFeatureEnabled()) {
310 vsyncThreadRunning_ = true;
311 threadLoop_ = std::thread([this] { this->ThreadMain(); });
312 std::string threadName = "DVSync-" + name;
313 pthread_setname_np(threadLoop_.native_handle(), threadName.c_str());
314 }
315 #endif
316 }
317
~VSyncDistributor()318 VSyncDistributor::~VSyncDistributor()
319 {
320 #if defined(RS_ENABLE_DVSYNC)
321 if (dvsync_->IsFeatureEnabled()) {
322 {
323 std::unique_lock<std::mutex> locker(mutex_);
324 vsyncThreadRunning_ = false;
325 }
326 if (threadLoop_.joinable()) {
327 {
328 std::unique_lock<std::mutex> locker(mutex_);
329 dvsync_->RNVNotify();
330 }
331 con_.notify_all();
332 threadLoop_.join();
333 }
334 }
335 #endif
336 }
337
AddConnection(const sptr<VSyncConnection>& connection, uint64_t windowNodeId)338 VsyncError VSyncDistributor::AddConnection(const sptr<VSyncConnection>& connection, uint64_t windowNodeId)
339 {
340 if (connection == nullptr) {
341 return VSYNC_ERROR_NULLPTR;
342 }
343 std::lock_guard<std::mutex> locker(mutex_);
344 int32_t proxyPid = connection->proxyPid_;
345 if (connectionCounter_[proxyPid] > VSYNC_CONNECTION_MAX_SIZE) {
346 VLOGE("You [%{public}d] have created too many vsync connection, please check!!!", proxyPid);
347 return VSYNC_ERROR_API_FAILED;
348 }
349 auto it = std::find(connections_.begin(), connections_.end(), connection);
350 if (it != connections_.end()) {
351 return VSYNC_ERROR_INVALID_ARGUMENTS;
352 }
353 RS_TRACE_NAME_FMT("Add VSyncConnection: %s", connection->info_.name_.c_str());
354 connections_.push_back(connection);
355 connectionCounter_[proxyPid]++;
356 if (windowNodeId != 0) {
357 connectionsMap_[windowNodeId].push_back(connection);
358 } else {
359 uint32_t tmpPid;
360 if (QosGetPidByName(connection->info_.name_, tmpPid) == VSYNC_ERROR_OK) {
361 connectionsMap_[tmpPid].push_back(connection);
362 }
363 }
364
365 return VSYNC_ERROR_OK;
366 }
367
RemoveConnection(const sptr<VSyncConnection>& connection)368 VsyncError VSyncDistributor::RemoveConnection(const sptr<VSyncConnection>& connection)
369 {
370 if (connection == nullptr) {
371 return VSYNC_ERROR_NULLPTR;
372 }
373 std::lock_guard<std::mutex> locker(mutex_);
374 int32_t proxyPid = connection->proxyPid_;
375 auto it = std::find(connections_.begin(), connections_.end(), connection);
376 if (it == connections_.end()) {
377 return VSYNC_ERROR_INVALID_ARGUMENTS;
378 }
379 RS_TRACE_NAME_FMT("Remove VSyncConnection: %s", connection->info_.name_.c_str());
380 connections_.erase(it);
381 connectionCounter_[proxyPid]--;
382 if (connectionCounter_[proxyPid] == 0) {
383 connectionCounter_.erase(proxyPid);
384 }
385 connectionsMap_.erase(connection->windowNodeId_);
386 uint32_t tmpPid;
387 if (QosGetPidByName(connection->info_.name_, tmpPid) == VSYNC_ERROR_OK) {
388 auto iter = connectionsMap_.find(tmpPid);
389 if (iter == connectionsMap_.end()) {
390 return VSYNC_ERROR_OK;
391 }
392 auto connIter = find(iter->second.begin(), iter->second.end(), connection);
393 if (connIter != iter->second.end()) {
394 iter->second.erase(connIter);
395 }
396 if (iter->second.empty()) {
397 connectionsMap_.erase(iter);
398 }
399 }
400 return VSYNC_ERROR_OK;
401 }
402
WaitForVsyncOrRequest(std::unique_lock<std::mutex> &locker)403 void VSyncDistributor::WaitForVsyncOrRequest(std::unique_lock<std::mutex> &locker)
404 {
405 if (!vsyncThreadRunning_) {
406 return;
407 }
408
409 // before con_ wait, notify the rnv_con.
410 #if defined(RS_ENABLE_DVSYNC)
411 dvsync_->RNVNotify();
412 if (!isRs_ && IsDVsyncOn()) {
413 con_.wait_for(locker, std::chrono::nanoseconds(dvsync_->WaitTime()), [this] { return dvsync_->WaitCond(); });
414 } else {
415 if (!(hasVsync_.load() && isRs_)) {
416 con_.wait(locker);
417 }
418 hasVsync_.store(false);
419 }
420 if (pendingRNVInVsync_) {
421 return;
422 }
423 if (IsDVsyncOn()) {
424 std::pair<bool, int64_t> result = dvsync_->DoPreExecute(locker, con_);
425 if (result.first) {
426 event_.timestamp = result.second;
427 lastDVsyncTS_.store(result.second);
428 event_.vsyncCount++;
429 if (vsyncEnabled_ == false) {
430 ScopedBytrace func(name_ + "_EnableVsync");
431 EnableVSync();
432 }
433 }
434 }
435 #else
436 con_.wait(locker);
437 #endif
438 }
439
Now()440 int64_t Now()
441 {
442 const auto &now = std::chrono::steady_clock::now().time_since_epoch();
443 return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
444 }
445
WaitForVsyncOrTimeOut(std::unique_lock<std::mutex> &locker)446 void VSyncDistributor::WaitForVsyncOrTimeOut(std::unique_lock<std::mutex> &locker)
447 {
448 #if defined(RS_ENABLE_DVSYNC)
449 dvsync_->RNVNotify();
450 #endif
451 if (con_.wait_for(locker, std::chrono::milliseconds(SOFT_VSYNC_PERIOD)) ==
452 std::cv_status::timeout) {
453 event_.timestamp = Now();
454 event_.vsyncCount++;
455 }
456 }
457
ThreadMain()458 void VSyncDistributor::ThreadMain()
459 {
460 // set thread priorty
461 setpriority(PRIO_PROCESS, 0, THREAD_PRIORTY);
462 struct sched_param param = {0};
463 param.sched_priority = SCHED_PRIORITY;
464 sched_setscheduler(0, SCHED_FIFO, ¶m);
465
466 #ifdef COMPOSER_SCHED_ENABLE
467 std::string threadName = "VSync-" + name_;
468 SubScribeSystemAbility(threadName);
469 #endif
470
471 int64_t timestamp;
472 while (vsyncThreadRunning_ == true) {
473 std::vector<sptr<VSyncConnection>> conns;
474 {
475 bool waitForVSync = false;
476 std::unique_lock<std::mutex> locker(mutex_);
477 CollectConns(waitForVSync, timestamp, conns, true);
478 // no vsync signal
479 if (timestamp == 0) {
480 // there is some connections request next vsync, enable vsync if vsync disable and
481 // and start the software vsync with wait_for function
482 if (waitForVSync == true && vsyncEnabled_ == false) {
483 EnableVSync();
484 WaitForVsyncOrTimeOut(locker);
485 } else {
486 // just wait request or vsync signal
487 WaitForVsyncOrRequest(locker);
488 }
489 RS_TRACE_NAME_FMT("%s_continue: waitForVSync %d, vsyncEnabled %d, dvsyncOn %d",
490 name_.c_str(), waitForVSync, vsyncEnabled_, IsDVsyncOn());
491 if ((isRs_ && event_.timestamp == 0) || !IsDVsyncOn()) {
492 continue;
493 } else {
494 timestamp = event_.timestamp;
495 }
496 } else if ((timestamp > 0) && (waitForVSync == false) && (isRs_ || !IsDVsyncOn())) {
497 // if there is a vsync signal but no vaild connections, we should disable vsync
498 RS_TRACE_NAME_FMT("%s_DisableVSync, there is no valid connections", name_.c_str());
499 DisableVSync();
500 continue;
501 }
502 }
503 if (!PostVSyncEventPreProcess(timestamp, conns)) {
504 continue;
505 } else {
506 // IMPORTANT: ScopedDebugTrace here will cause frame loss.
507 RS_TRACE_NAME_FMT("%s_SendVsync", name_.c_str());
508 }
509 PostVSyncEvent(conns, timestamp, true);
510 }
511 }
512
CollectConns(bool &waitForVSync, int64_t ×tamp, std::vector<sptr<VSyncConnection>> &conns, bool isDvsyncThread)513 void VSyncDistributor::CollectConns(bool &waitForVSync, int64_t ×tamp,
514 std::vector<sptr<VSyncConnection>> &conns, bool isDvsyncThread)
515 {
516 if (isDvsyncThread) {
517 timestamp = event_.timestamp;
518 event_.timestamp = 0;
519 }
520 if (vsyncMode_ == VSYNC_MODE_LTPO) {
521 CollectConnectionsLTPO(waitForVSync, timestamp, conns, event_.vsyncPulseCount, isDvsyncThread);
522 } else {
523 CollectConnections(waitForVSync, timestamp, conns, event_.vsyncCount, isDvsyncThread);
524 }
525 }
526
PostVSyncEventPreProcess(int64_t ×tamp, std::vector<sptr<VSyncConnection>> &conns)527 bool VSyncDistributor::PostVSyncEventPreProcess(int64_t ×tamp, std::vector<sptr<VSyncConnection>> &conns)
528 {
529 #if defined(RS_ENABLE_DVSYNC)
530 bool waitForVSync = false;
531 // ensure the preexecution only gets ahead for at most one period(i.e., 3 buffer rotation)
532 if (IsDVsyncOn()) {
533 {
534 std::unique_lock<std::mutex> locker(mutex_);
535 dvsync_->MarkDistributorSleep(true);
536 dvsync_->RNVNotify();
537 dvsync_->DelayBeforePostEvent(event_.timestamp, locker);
538 dvsync_->MarkDistributorSleep(false);
539 CollectConns(waitForVSync, timestamp, conns, true);
540 hasVsync_.store(false);
541 }
542 // if getting switched into vsync mode after sleep
543 if (!IsDVsyncOn()) {
544 ScopedBytrace func("NoAccumulateInVsync");
545 lastDVsyncTS_.store(0); // ensure further OnVSyncEvent do not skip
546 for (auto conn : conns) {
547 RequestNextVSync(conn);
548 } // resend RNV for vsync
549 return false; // do not accumulate frame;
550 }
551 } else {
552 std::unique_lock<std::mutex> locker(mutex_);
553 hasVsync_.store(false);
554 }
555 {
556 std::unique_lock<std::mutex> locker(mutex_);
557 pendingRNVInVsync_ = false;
558 if (IsUiDvsyncOn()) {
559 event_.period = dvsync_->GetPeriod();
560 }
561 }
562 #endif
563 return true;
564 }
565
EnableVSync()566 void VSyncDistributor::EnableVSync()
567 {
568 if (controller_ != nullptr && vsyncEnabled_ == false) {
569 controller_->SetCallback(this);
570 controller_->SetEnable(true, vsyncEnabled_);
571 }
572 }
573
DisableVSync()574 void VSyncDistributor::DisableVSync()
575 {
576 if (controller_ != nullptr && vsyncEnabled_ == true) {
577 controller_->SetEnable(false, vsyncEnabled_);
578 }
579 }
580
581 #if defined(RS_ENABLE_DVSYNC)
OnDVSyncTrigger(int64_t now, int64_t period, uint32_t refreshRate, VSyncMode vsyncMode, uint32_t vsyncMaxRefreshRate)582 void VSyncDistributor::OnDVSyncTrigger(int64_t now, int64_t period,
583 uint32_t refreshRate, VSyncMode vsyncMode, uint32_t vsyncMaxRefreshRate)
584 {
585 std::unique_lock<std::mutex> locker(mutex_);
586 vsyncMode_ = vsyncMode;
587 dvsync_->RuntimeSwitch();
588 if (IsDVsyncOn()) {
589 RS_TRACE_NAME_FMT("VSyncD onVSyncEvent, now:%ld", now);
590 } else {
591 RS_TRACE_NAME_FMT("VSync onVSyncEvent, now:%ld", now);
592 }
593 event_.period = period;
594
595 dvsync_->RecordVSync(now, period, refreshRate);
596 dvsync_->NotifyPreexecuteWait();
597
598 SendConnectionsToVSyncWindow(now, period, refreshRate, vsyncMode, locker);
599 // when dvsync switch to vsync, skip all vsync events within one period from the pre-rendered timestamp
600 if (dvsync_->NeedSkipDVsyncPrerenderedFrame()) {
601 return;
602 }
603
604 // When vsync switches to dvsync, need to handle pending RNVs during vsync
605 if (!IsDVsyncOn() || pendingRNVInVsync_) {
606 event_.timestamp = now;
607 event_.vsyncCount++;
608 }
609
610 if (refreshRate > 0) {
611 event_.vsyncPulseCount += static_cast<int64_t>(vsyncMaxRefreshRate / refreshRate);
612 generatorRefreshRate_ = refreshRate;
613 }
614
615 ChangeConnsRateLocked(vsyncMaxRefreshRate);
616 RS_TRACE_NAME_FMT("pendingRNVInVsync: %d DVSyncOn: %d isRS:%d", pendingRNVInVsync_, IsDVsyncOn(), isRs_);
617 if (dvsync_->WaitCond() || pendingRNVInVsync_) {
618 con_.notify_all();
619 } else {
620 CheckNeedDisableDvsync(now, period);
621 }
622 }
623 #endif
624
OnVSyncTrigger(int64_t now, int64_t period, uint32_t refreshRate, VSyncMode vsyncMode, uint32_t vsyncMaxRefreshRate)625 void VSyncDistributor::OnVSyncTrigger(int64_t now, int64_t period,
626 uint32_t refreshRate, VSyncMode vsyncMode, uint32_t vsyncMaxRefreshRate)
627 {
628 std::vector<sptr<VSyncConnection>> conns;
629 uint32_t generatorRefreshRate;
630 int64_t vsyncCount;
631
632 {
633 bool waitForVSync = false;
634 std::lock_guard<std::mutex> locker(mutex_);
635 event_.vsyncCount++;
636 vsyncCount = event_.vsyncCount;
637
638 if (refreshRate > 0) {
639 event_.vsyncPulseCount += static_cast<int64_t>(vsyncMaxRefreshRate / refreshRate);
640 generatorRefreshRate_ = refreshRate;
641 }
642 vsyncMode_ = vsyncMode;
643 ChangeConnsRateLocked(vsyncMaxRefreshRate);
644
645 if (vsyncMode_ == VSYNC_MODE_LTPO) {
646 CollectConnectionsLTPO(waitForVSync, now, conns, event_.vsyncPulseCount);
647 } else {
648 CollectConnections(waitForVSync, now, conns, event_.vsyncCount);
649 }
650 if (!waitForVSync) {
651 DisableVSync();
652 return;
653 }
654
655 countTraceValue_ = (countTraceValue_ + 1) % 2; // 2 : change num
656 CountTrace(HITRACE_TAG_GRAPHIC_AGP, "VSync-" + name_, countTraceValue_);
657
658 generatorRefreshRate = generatorRefreshRate_;
659 }
660
661 for (uint32_t i = 0; i < conns.size(); i++) {
662 int64_t actualPeriod = period;
663 if ((generatorRefreshRate > 0) && (conns[i]->refreshRate_ > 0) &&
664 (generatorRefreshRate % conns[i]->refreshRate_ == 0)) {
665 actualPeriod = period * static_cast<int64_t>(generatorRefreshRate / conns[i]->refreshRate_);
666 }
667 int32_t ret = conns[i]->PostEvent(now, actualPeriod, vsyncCount);
668 VLOGD("Distributor name:%{public}s, connection name:%{public}s, ret:%{public}d",
669 name_.c_str(), conns[i]->info_.name.c_str(), ret);
670 if (ret == 0 || ret == ERRNO_OTHER) {
671 RemoveConnection(conns[i]);
672 } else if (ret == ERRNO_EAGAIN) {
673 std::lock_guard<std::mutex> locker(mutex_);
674 // Trigger VSync Again for LTPO
675 conns[i]->triggerThisTime_ = true;
676 // Exclude SetVSyncRate for LTPS
677 if (conns[i]->rate_ < 0) {
678 conns[i]->rate_ = 0;
679 }
680 }
681 }
682 }
683
OnVSyncEvent(int64_t now, int64_t period, uint32_t refreshRate, VSyncMode vsyncMode, uint32_t vsyncMaxRefreshRate)684 void VSyncDistributor::OnVSyncEvent(int64_t now, int64_t period,
685 uint32_t refreshRate, VSyncMode vsyncMode, uint32_t vsyncMaxRefreshRate)
686 {
687 #if defined(RS_ENABLE_DVSYNC)
688 if (dvsync_->IsFeatureEnabled()) {
689 OnDVSyncTrigger(now, period, refreshRate, vsyncMode, vsyncMaxRefreshRate);
690 } else
691 #endif
692 {
693 OnVSyncTrigger(now, period, refreshRate, vsyncMode, vsyncMaxRefreshRate);
694 }
695 }
696
697 #if defined(RS_ENABLE_DVSYNC)
SendConnectionsToVSyncWindow(int64_t now, int64_t period, uint32_t refreshRate, VSyncMode vsyncMode, std::unique_lock<std::mutex> &locker)698 void VSyncDistributor::SendConnectionsToVSyncWindow(int64_t now, int64_t period, uint32_t refreshRate,
699 VSyncMode vsyncMode, std::unique_lock<std::mutex> &locker)
700 {
701 std::vector<sptr<VSyncConnection>> conns;
702 bool waitForVSync = false;
703 if (isRs_ || GetUIDVsyncPid() == 0) {
704 return;
705 }
706 CollectConns(waitForVSync, now, conns, false);
707 locker.unlock();
708 PostVSyncEvent(conns, now, false);
709 locker.lock();
710 }
711
GetUIDVsyncPid()712 int32_t VSyncDistributor::GetUIDVsyncPid()
713 {
714 int32_t pid = 0;
715 if (!isRs_) {
716 pid = dvsync_->GetProxyPid();
717 }
718 return pid;
719 }
720 #endif
721
CheckNeedDisableDvsync(int64_t now, int64_t period)722 void VSyncDistributor::CheckNeedDisableDvsync(int64_t now, int64_t period)
723 {
724 #if defined(RS_ENABLE_DVSYNC)
725 if (!isRs_ && IsDVsyncOn()) {
726 return;
727 }
728 // When Dvsync on, if the RequestNextVsync is not invoked within three period and SetVSyncRate
729 // is not invoked either, execute DisableVSync.
730 for (uint32_t i = 0; i < connections_.size(); i++) {
731 if (connections_[i]->triggerThisTime_ || connections_[i]->rate_ >= 0) {
732 return;
733 }
734 }
735 if (now - dvsync_->GetLastRnvTS() > 3 * period) { // 3 period
736 ScopedBytrace func(name_ + "_DisableVsync");
737 DisableVSync();
738 }
739 #endif
740 }
741
742 /* std::pair<id, refresh rate> */
OnConnsRefreshRateChanged(const std::vector<std::pair<uint64_t, uint32_t>> &refreshRates)743 void VSyncDistributor::OnConnsRefreshRateChanged(const std::vector<std::pair<uint64_t, uint32_t>> &refreshRates)
744 {
745 std::lock_guard<std::mutex> locker(changingConnsRefreshRatesMtx_);
746 for (auto refreshRate : refreshRates) {
747 bool found = false;
748 for (auto it = changingConnsRefreshRates_.begin(); it != changingConnsRefreshRates_.end(); it++) {
749 if ((*it).first == refreshRate.first) { // first is linkerId
750 (*it).second = refreshRate.second; // second is refreshRate
751 found = true;
752 break;
753 }
754 }
755 if (!found) {
756 changingConnsRefreshRates_.push_back(refreshRate);
757 }
758 }
759 }
760
SubScribeSystemAbility(const std::string& threadName)761 void VSyncDistributor::SubScribeSystemAbility(const std::string& threadName)
762 {
763 VLOGD("%{public}s", __func__);
764 sptr<ISystemAbilityManager> systemAbilityManager =
765 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
766 if (!systemAbilityManager) {
767 VLOGE("%{public}s failed to get system ability manager client", __func__);
768 return;
769 }
770 std::string strUid = std::to_string(getuid());
771 std::string strPid = std::to_string(getpid());
772 std::string strTid = std::to_string(gettid());
773
774 saStatusChangeListener_ = new VSyncSystemAbilityListener(threadName, strUid, strPid, strTid);
775 int32_t ret = systemAbilityManager->SubscribeSystemAbility(RES_SCHED_SYS_ABILITY_ID, saStatusChangeListener_);
776 if (ret != ERR_OK) {
777 VLOGE("%{public}s subscribe system ability %{public}d failed.", __func__, RES_SCHED_SYS_ABILITY_ID);
778 saStatusChangeListener_ = nullptr;
779 }
780 }
781
CollectConnections(bool &waitForVSync, int64_t timestamp, std::vector<sptr<VSyncConnection>> &conns, int64_t vsyncCount, bool isDvsyncThread)782 void VSyncDistributor::CollectConnections(bool &waitForVSync, int64_t timestamp,
783 std::vector<sptr<VSyncConnection>> &conns, int64_t vsyncCount, bool isDvsyncThread)
784 {
785 #if defined(RS_ENABLE_DVSYNC)
786 auto uiDVsyncPid = GetUIDVsyncPid();
787 #endif
788 for (uint32_t i = 0; i < connections_.size(); i++) {
789 #if defined(RS_ENABLE_DVSYNC)
790 if (uiDVsyncPid != 0 && ((!isDvsyncThread && connections_[i]->proxyPid_ == uiDVsyncPid) ||
791 (isDvsyncThread && connections_[i]->proxyPid_ != uiDVsyncPid))) {
792 continue;
793 }
794 #endif
795 int32_t rate = connections_[i]->highPriorityState_ ? connections_[i]->highPriorityRate_ :
796 connections_[i]->rate_;
797
798 if (rate < 0) {
799 continue;
800 }
801
802 if (rate == 0) { // for RequestNextVSync
803 waitForVSync = true;
804 if (timestamp > 0) {
805 connections_[i]->rate_ = -1;
806 connections_[i]->triggerThisTime_ = false;
807 conns.push_back(connections_[i]);
808 }
809 continue;
810 }
811
812 RS_TRACE_NAME_FMT("CollectConnections name:%s, proxyPid:%d, highPriorityState_:%d, highPriorityRate_:%d"
813 ", rate_:%d, timestamp:%ld, vsyncCount:%ld", connections_[i]->info_.name_.c_str(),
814 connections_[i]->proxyPid_, connections_[i]->highPriorityState_,
815 connections_[i]->highPriorityRate_, connections_[i]->rate_, timestamp, vsyncCount);
816
817 if (connections_[i]->rate_ == 0) { // for SetHighPriorityVSyncRate with RequestNextVSync
818 waitForVSync = true;
819 if (timestamp > 0 && (vsyncCount % rate == 0)) {
820 connections_[i]->rate_ = -1;
821 connections_[i]->triggerThisTime_ = false;
822 conns.push_back(connections_[i]);
823 }
824 } else if (connections_[i]->rate_ > 0) { // for SetVSyncRate
825 waitForVSync = true;
826 if (timestamp > 0 && (vsyncCount % rate == 0)) {
827 conns.push_back(connections_[i]);
828 }
829 }
830 }
831 }
832
CollectConnectionsLTPO(bool &waitForVSync, int64_t timestamp, std::vector<sptr<VSyncConnection>> &conns, int64_t vsyncCount, bool isDvsyncThread)833 void VSyncDistributor::CollectConnectionsLTPO(bool &waitForVSync, int64_t timestamp,
834 std::vector<sptr<VSyncConnection>> &conns, int64_t vsyncCount, bool isDvsyncThread)
835 {
836 #if defined(RS_ENABLE_DVSYNC)
837 auto uiDVsyncPid = GetUIDVsyncPid();
838 #endif
839 for (uint32_t i = 0; i < connections_.size(); i++) {
840 #if defined(RS_ENABLE_DVSYNC)
841 if (uiDVsyncPid != 0 && ((!isDvsyncThread && connections_[i]->proxyPid_ == uiDVsyncPid) ||
842 (isDvsyncThread && connections_[i]->proxyPid_ != uiDVsyncPid))) {
843 continue;
844 }
845 #endif
846 SCOPED_DEBUG_TRACE_FMT("CollectConnectionsLTPO, i:%d, name:%s, rate:%d, vsyncPulseFreq:%u"
847 ", referencePulseCount:%ld, vsyncCount:%d, highPriorityRate_:%d", i, connections_[i]->info_.name_.c_str(),
848 connections_[i]->rate_, connections_[i]->vsyncPulseFreq_, connections_[i]->referencePulseCount_,
849 vsyncCount, connections_[i]->highPriorityRate_);
850 if (!connections_[i]->triggerThisTime_ && connections_[i]->rate_ <= 0) {
851 continue;
852 }
853 waitForVSync = true;
854 if (timestamp <= 0) {
855 break;
856 }
857 int64_t vsyncPulseFreq = static_cast<int64_t>(connections_[i]->vsyncPulseFreq_);
858 if (vsyncPulseFreq == 0) {
859 continue;
860 }
861 if ((vsyncCount - connections_[i]->referencePulseCount_) % vsyncPulseFreq == 0) {
862 connections_[i]->triggerThisTime_ = false;
863 if (connections_[i]->rate_ == 0) {
864 connections_[i]->rate_ = -1;
865 }
866 conns.push_back(connections_[i]);
867 }
868 }
869 }
870
PostVSyncEvent(const std::vector<sptr<VSyncConnection>> &conns, int64_t timestamp, bool isDvsyncThread)871 void VSyncDistributor::PostVSyncEvent(const std::vector<sptr<VSyncConnection>> &conns,
872 int64_t timestamp, bool isDvsyncThread)
873 {
874 #if defined(RS_ENABLE_DVSYNC)
875 if (isDvsyncThread) {
876 std::unique_lock<std::mutex> locker(mutex_);
877 dvsync_->RecordPostEvent(conns, timestamp);
878 }
879 #endif
880 uint32_t generatorRefreshRate = 0;
881 int64_t eventPeriod = 0;
882 int64_t vsyncCount = 0;
883 {
884 std::unique_lock<std::mutex> locker(mutex_);
885 generatorRefreshRate = generatorRefreshRate_;
886 eventPeriod = event_.period;
887 vsyncCount = event_.vsyncCount;
888 }
889 for (uint32_t i = 0; i < conns.size(); i++) {
890 int64_t period = eventPeriod;
891 if ((generatorRefreshRate > 0) && (conns[i]->refreshRate_ > 0) &&
892 (generatorRefreshRate % conns[i]->refreshRate_ == 0)) {
893 period = eventPeriod * static_cast<int64_t>(generatorRefreshRate / conns[i]->refreshRate_);
894 }
895 int32_t ret = conns[i]->PostEvent(timestamp, period, vsyncCount);
896 VLOGD("Distributor name:%{public}s, connection name:%{public}s, ret:%{public}d",
897 name_.c_str(), conns[i]->info_.name_.c_str(), ret);
898 if (ret == 0 || ret == ERRNO_OTHER) {
899 RemoveConnection(conns[i]);
900 } else if (ret == ERRNO_EAGAIN) {
901 std::unique_lock<std::mutex> locker(mutex_);
902 // Trigger VSync Again for LTPO
903 conns[i]->triggerThisTime_ = true;
904 #if defined(RS_ENABLE_DVSYNC)
905 if (isDvsyncThread) {
906 hasVsync_.store(true);
907 }
908 #endif
909 // Exclude SetVSyncRate for LTPS
910 if (conns[i]->rate_ < 0) {
911 conns[i]->rate_ = 0;
912 }
913 }
914 }
915 }
916
RequestNextVSync(const sptr<VSyncConnection> &connection, const std::string &fromWhom, int64_t lastVSyncTS)917 VsyncError VSyncDistributor::RequestNextVSync(const sptr<VSyncConnection> &connection, const std::string &fromWhom,
918 int64_t lastVSyncTS)
919 {
920 if (connection == nullptr) {
921 VLOGE("connection is nullptr");
922 return VSYNC_ERROR_NULLPTR;
923 }
924
925 ScopedBytrace func(connection->info_.name_ + "_RequestNextVSync");
926 std::unique_lock<std::mutex> locker(mutex_);
927
928 #if defined(RS_ENABLE_DVSYNC)
929 if (IsDVsyncOn() && isRs_) {
930 dvsync_->RNVWait(locker);
931 }
932 #endif
933
934 auto it = find(connections_.begin(), connections_.end(), connection);
935 if (it == connections_.end()) {
936 VLOGE("connection is invalid arguments");
937 #if defined(RS_ENABLE_DVSYNC)
938 if (IsDVsyncOn()) {
939 dvsync_->RNVNotify();
940 }
941 #endif
942 return VSYNC_ERROR_INVALID_ARGUMENTS;
943 }
944 // record RNV and lastVSyncTS for D-VSYNC
945 #if defined(RS_ENABLE_DVSYNC)
946 dvsync_->RecordRNV(connection, fromWhom, lastVSyncTS);
947 if (!IsDVsyncOn()) {
948 pendingRNVInVsync_ = true;
949 }
950 #endif
951 if (connection->rate_ < 0) {
952 connection->rate_ = 0;
953 }
954 connection->triggerThisTime_ = true;
955 #if defined(RS_ENABLE_DVSYNC)
956 hasVsync_.store(true);
957 if (dvsync_->IsFeatureEnabled()) {
958 con_.notify_all();
959 } else
960 #endif
961 {
962 EnableVSync();
963 }
964 VLOGD("conn name:%{public}s, rate:%{public}d", connection->info_.name_.c_str(), connection->rate_);
965 return VSYNC_ERROR_OK;
966 }
967
SetVSyncRate(int32_t rate, const sptr<VSyncConnection>& connection)968 VsyncError VSyncDistributor::SetVSyncRate(int32_t rate, const sptr<VSyncConnection>& connection)
969 {
970 if (rate < -1 || connection == nullptr) {
971 return VSYNC_ERROR_INVALID_ARGUMENTS;
972 }
973 std::lock_guard<std::mutex> locker(mutex_);
974 auto it = find(connections_.begin(), connections_.end(), connection);
975 if (it == connections_.end()) {
976 return VSYNC_ERROR_INVALID_ARGUMENTS;
977 }
978 if (connection->rate_ == rate) {
979 return VSYNC_ERROR_INVALID_ARGUMENTS;
980 }
981 connection->rate_ = rate;
982 VLOGD("conn name:%{public}s", connection->info_.name_.c_str());
983 #if defined(RS_ENABLE_DVSYNC)
984 if (dvsync_->IsFeatureEnabled()) {
985 con_.notify_all();
986 } else
987 #endif
988 {
989 EnableVSync();
990 }
991 return VSYNC_ERROR_OK;
992 }
993
SetHighPriorityVSyncRate(int32_t highPriorityRate, const sptr<VSyncConnection>& connection)994 VsyncError VSyncDistributor::SetHighPriorityVSyncRate(int32_t highPriorityRate, const sptr<VSyncConnection>& connection)
995 {
996 if (highPriorityRate <= 0 || connection == nullptr) {
997 return VSYNC_ERROR_INVALID_ARGUMENTS;
998 }
999
1000 std::lock_guard<std::mutex> locker(mutex_);
1001 auto it = find(connections_.begin(), connections_.end(), connection);
1002 if (it == connections_.end()) {
1003 return VSYNC_ERROR_INVALID_ARGUMENTS;
1004 }
1005 if (connection->highPriorityRate_ == highPriorityRate) {
1006 return VSYNC_ERROR_INVALID_ARGUMENTS;
1007 }
1008 connection->highPriorityRate_ = highPriorityRate;
1009 connection->highPriorityState_ = true;
1010 VLOGD("in, conn name:%{public}s, highPriorityRate:%{public}d", connection->info_.name_.c_str(),
1011 connection->highPriorityRate_);
1012 #if defined(RS_ENABLE_DVSYNC)
1013 if (dvsync_->IsFeatureEnabled()) {
1014 con_.notify_all();
1015 } else
1016 #endif
1017 {
1018 EnableVSync();
1019 }
1020 return VSYNC_ERROR_OK;
1021 }
1022
QosGetPidByName(const std::string& name, uint32_t& pid)1023 VsyncError VSyncDistributor::QosGetPidByName(const std::string& name, uint32_t& pid)
1024 {
1025 if (name.find("WM") == std::string::npos) {
1026 return VSYNC_ERROR_INVALID_ARGUMENTS;
1027 }
1028 // exclude names like NWeb_WM or ArkWebCore_WM
1029 if ((name.find("NWeb") != std::string::npos) || (name.find("ArkWebCore") != std::string::npos)) {
1030 return VSYNC_ERROR_INVALID_ARGUMENTS;
1031 }
1032 std::string::size_type pos = name.find("_");
1033 if (pos == std::string::npos || (pos + 1) >= name.size()) {
1034 return VSYNC_ERROR_INVALID_ARGUMENTS;
1035 }
1036 pid = static_cast<uint32_t>(stoi(name.substr(pos + 1)));
1037 return VSYNC_ERROR_OK;
1038 }
1039
SetQosVSyncRateByPid(uint32_t pid, int32_t rate, bool isSystemAnimateScene)1040 VsyncError VSyncDistributor::SetQosVSyncRateByPid(uint32_t pid, int32_t rate, bool isSystemAnimateScene)
1041 {
1042 // only set vsync rate by pid in SystemAnimateSecne
1043 if (!isSystemAnimateScene && rate != DEFAULT_VSYNC_RATE) {
1044 return VSYNC_ERROR_OK;
1045 }
1046 auto iter = connectionsMap_.find(pid);
1047 if (iter == connectionsMap_.end()) {
1048 VLOGD("%{public}s:%{public}d pid[%{public}u] can not found", __func__, __LINE__, pid);
1049 return VSYNC_ERROR_INVALID_ARGUMENTS;
1050 }
1051 bool isNeedNotify = false;
1052 for (auto connection : iter->second) {
1053 uint32_t tmpPid;
1054 if (QosGetPidByName(connection->info_.name_, tmpPid) != VSYNC_ERROR_OK || tmpPid != pid) {
1055 continue;
1056 }
1057 if (connection->highPriorityRate_ != rate) {
1058 connection->highPriorityRate_ = rate;
1059 connection->highPriorityState_ = true;
1060 VLOGD("in, conn name:%{public}s, highPriorityRate:%{public}d", connection->info_.name_.c_str(),
1061 connection->highPriorityRate_);
1062 isNeedNotify = true;
1063 }
1064 }
1065
1066 if (isNeedNotify) {
1067 #if defined(RS_ENABLE_DVSYNC)
1068 if (dvsync_->IsFeatureEnabled()) {
1069 con_.notify_all();
1070 } else
1071 #endif
1072 {
1073 EnableVSync();
1074 }
1075 }
1076
1077 return VSYNC_ERROR_OK;
1078 }
1079
ExtractPid(uint64_t id)1080 constexpr pid_t VSyncDistributor::ExtractPid(uint64_t id)
1081 {
1082 constexpr uint32_t bits = 32u;
1083 return static_cast<pid_t>(id >> bits);
1084 }
1085
SetQosVSyncRate(uint64_t windowNodeId, int32_t rate, bool isSystemAnimateScene)1086 VsyncError VSyncDistributor::SetQosVSyncRate(uint64_t windowNodeId, int32_t rate, bool isSystemAnimateScene)
1087 {
1088 std::lock_guard<std::mutex> locker(mutex_);
1089 VsyncError resCode = SetQosVSyncRateByPid(ExtractPid(windowNodeId), rate, isSystemAnimateScene);
1090 auto iter = connectionsMap_.find(windowNodeId);
1091 if (iter == connectionsMap_.end()) {
1092 return resCode;
1093 }
1094 bool isNeedNotify = false;
1095 for (auto& connection : iter->second) {
1096 if (connection != nullptr && connection->highPriorityRate_ != rate) {
1097 connection->highPriorityRate_ = rate;
1098 connection->highPriorityState_ = true;
1099 VLOGD("in, conn name:%{public}s, highPriorityRate:%{public}d", connection->info_.name_.c_str(),
1100 connection->highPriorityRate_);
1101 isNeedNotify = true;
1102 }
1103 }
1104 if (isNeedNotify) {
1105 #if defined(RS_ENABLE_DVSYNC)
1106 if (dvsync_->IsFeatureEnabled()) {
1107 con_.notify_all();
1108 } else
1109 #endif
1110 {
1111 EnableVSync();
1112 }
1113 }
1114 return VSYNC_ERROR_OK;
1115 }
1116
ChangeConnsRateLocked(uint32_t vsyncMaxRefreshRate)1117 void VSyncDistributor::ChangeConnsRateLocked(uint32_t vsyncMaxRefreshRate)
1118 {
1119 std::lock_guard<std::mutex> locker(changingConnsRefreshRatesMtx_);
1120 for (auto connRefreshRate : changingConnsRefreshRates_) {
1121 for (auto conn : connections_) {
1122 if (conn->id_ != connRefreshRate.first) {
1123 continue;
1124 }
1125 uint32_t refreshRate = connRefreshRate.second;
1126 if ((generatorRefreshRate_ == 0) || (refreshRate == 0) ||
1127 (vsyncMaxRefreshRate % refreshRate != 0) || (generatorRefreshRate_ % refreshRate != 0)) {
1128 conn->refreshRate_ = 0;
1129 conn->vsyncPulseFreq_ = 1;
1130 continue;
1131 }
1132 conn->refreshRate_ = refreshRate;
1133 conn->vsyncPulseFreq_ = vsyncMaxRefreshRate / refreshRate;
1134 conn->referencePulseCount_ = event_.vsyncPulseCount;
1135 }
1136 }
1137 changingConnsRefreshRates_.clear();
1138 }
1139
IsDVsyncOn()1140 bool VSyncDistributor::IsDVsyncOn()
1141 {
1142 #if defined(RS_ENABLE_DVSYNC)
1143 return dvsync_->IsEnabledAndOn();
1144 #else
1145 return false;
1146 #endif
1147 }
1148
SetFrameIsRender(bool isRender)1149 void VSyncDistributor::SetFrameIsRender(bool isRender)
1150 {
1151 #if defined(RS_ENABLE_DVSYNC)
1152 std::unique_lock<std::mutex> locker(mutex_);
1153 ScopedBytrace trace("SetFrameIsRender:" + std::to_string(isRender));
1154 if (isRender) {
1155 dvsync_->UnMarkRSNotRendering();
1156 } else {
1157 dvsync_->MarkRSNotRendering();
1158 }
1159 #endif
1160 }
1161
MarkRSAnimate()1162 void VSyncDistributor::MarkRSAnimate()
1163 {
1164 #if defined(RS_ENABLE_DVSYNC)
1165 dvsync_->MarkRSAnimate();
1166 #endif
1167 }
1168
UnmarkRSAnimate()1169 void VSyncDistributor::UnmarkRSAnimate()
1170 {
1171 #if defined(RS_ENABLE_DVSYNC)
1172 dvsync_->UnmarkRSAnimate();
1173 #endif
1174 }
1175
HasPendingUIRNV()1176 bool VSyncDistributor::HasPendingUIRNV()
1177 {
1178 #if defined(RS_ENABLE_DVSYNC)
1179 return dvsync_->HasPendingUIRNV();
1180 #else
1181 return false;
1182 #endif
1183 }
1184
SetUiDvsyncSwitch(bool dvsyncSwitch, const sptr<VSyncConnection> &connection)1185 VsyncError VSyncDistributor::SetUiDvsyncSwitch(bool dvsyncSwitch, const sptr<VSyncConnection> &connection)
1186 {
1187 #if defined(RS_ENABLE_DVSYNC)
1188 std::lock_guard<std::mutex> locker(mutex_);
1189 dvsync_->RuntimeMark(connection, dvsyncSwitch);
1190 #endif
1191 return VSYNC_ERROR_OK;
1192 }
1193
SetUiDvsyncConfig(int32_t bufferCount)1194 VsyncError VSyncDistributor::SetUiDvsyncConfig(int32_t bufferCount)
1195 {
1196 #if defined(RS_ENABLE_DVSYNC)
1197 std::lock_guard<std::mutex> locker(mutex_);
1198 dvsync_->SetUiDvsyncConfig(bufferCount);
1199 #endif
1200 return VSYNC_ERROR_OK;
1201 }
1202
SetNativeDVSyncSwitch(bool dvsyncSwitch, const sptr<VSyncConnection> &connection)1203 VsyncError VSyncDistributor::SetNativeDVSyncSwitch(bool dvsyncSwitch, const sptr<VSyncConnection> &connection)
1204 {
1205 #if defined(RS_ENABLE_DVSYNC)
1206 std::lock_guard<std::mutex> locker(mutex_);
1207 dvsync_->RuntimeMark(connection, dvsyncSwitch, true);
1208 #endif
1209 return VSYNC_ERROR_OK;
1210 }
1211
GetRefreshRate()1212 uint32_t VSyncDistributor::GetRefreshRate()
1213 {
1214 #if defined(RS_ENABLE_DVSYNC)
1215 std::lock_guard<std::mutex> locker(mutex_);
1216 return dvsync_->GetRefreshRate();
1217 #else
1218 return generatorRefreshRate_;
1219 #endif
1220 }
1221
RecordVsyncModeChange(uint32_t refreshRate, int64_t period)1222 void VSyncDistributor::RecordVsyncModeChange(uint32_t refreshRate, int64_t period)
1223 {
1224 #if defined(RS_ENABLE_DVSYNC)
1225 std::lock_guard<std::mutex> locker(mutex_);
1226 dvsync_->RecordVsyncModeChange(refreshRate, period);
1227 #endif
1228 }
1229
IsUiDvsyncOn()1230 bool VSyncDistributor::IsUiDvsyncOn()
1231 {
1232 #if defined(RS_ENABLE_DVSYNC)
1233 return dvsync_->IsUiDvsyncOn();
1234 #else
1235 return false;
1236 #endif
1237 }
1238
GetUiCommandDelayTime()1239 int64_t VSyncDistributor::GetUiCommandDelayTime()
1240 {
1241 #if defined(RS_ENABLE_DVSYNC)
1242 return dvsync_->GetUiCommandDelayTime();
1243 #else
1244 return 0;
1245 #endif
1246 }
1247
UpdatePendingReferenceTime(int64_t &timeStamp)1248 void VSyncDistributor::UpdatePendingReferenceTime(int64_t &timeStamp)
1249 {
1250 #if defined(RS_ENABLE_DVSYNC)
1251 if (IsDVsyncOn()) {
1252 dvsync_->UpdatePendingReferenceTime(timeStamp);
1253 }
1254 #endif
1255 }
1256
GetRealTimeOffsetOfDvsync(int64_t time)1257 uint64_t VSyncDistributor::GetRealTimeOffsetOfDvsync(int64_t time)
1258 {
1259 #if defined(RS_ENABLE_DVSYNC)
1260 if (IsDVsyncOn()) {
1261 return dvsync_->GetRealTimeOffsetOfDvsync(time);
1262 }
1263 #endif
1264 return 0;
1265 }
1266
SetHardwareTaskNum(uint32_t num)1267 void VSyncDistributor::SetHardwareTaskNum(uint32_t num)
1268 {
1269 #if defined(RS_ENABLE_DVSYNC)
1270 if (IsDVsyncOn()) {
1271 dvsync_->SetHardwareTaskNum(num);
1272 }
1273 #endif
1274 }
1275
GetVsyncCount()1276 int64_t VSyncDistributor::GetVsyncCount()
1277 {
1278 std::unique_lock<std::mutex> locker(mutex_);
1279 return event_.vsyncCount;
1280 }
1281 }
1282 }
1283