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_) {
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
SetUiDvsyncConfig(int32_t bufferCount)259 VsyncError VSyncConnection::SetUiDvsyncConfig(int32_t bufferCount)
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->SetUiDvsyncConfig(bufferCount);
277 }
278
VSyncDistributor(sptr<VSyncController> controller,std::string name)279 VSyncDistributor::VSyncDistributor(sptr<VSyncController> controller, std::string name)
280 : controller_(controller), mutex_(), con_(), connections_(),
281 event_(), vsyncEnabled_(false), name_(name)
282 {
283 static const std::string DEFAULT_RS_NAME = "rs";
284 if (name == DEFAULT_RS_NAME) {
285 isRs_ = true;
286 }
287 #if defined(RS_ENABLE_DVSYNC)
288 dvsync_ = new DVsync(isRs_);
289 if (dvsync_->IsFeatureEnabled()) {
290 vsyncThreadRunning_ = true;
291 threadLoop_ = std::thread([this] { this->ThreadMain(); });
292 std::string threadName = "DVSync-" + name;
293 pthread_setname_np(threadLoop_.native_handle(), threadName.c_str());
294 }
295 #endif
296 }
297
~VSyncDistributor()298 VSyncDistributor::~VSyncDistributor()
299 {
300 #if defined(RS_ENABLE_DVSYNC)
301 if (dvsync_->IsFeatureEnabled()) {
302 {
303 std::unique_lock<std::mutex> locker(mutex_);
304 vsyncThreadRunning_ = false;
305 }
306 if (threadLoop_.joinable()) {
307 {
308 std::unique_lock<std::mutex> locker(mutex_);
309 dvsync_->RNVNotify();
310 }
311 con_.notify_all();
312 threadLoop_.join();
313 }
314 }
315 #endif
316 }
317
AddConnection(const sptr<VSyncConnection> & connection,uint64_t windowNodeId)318 VsyncError VSyncDistributor::AddConnection(const sptr<VSyncConnection>& connection, uint64_t windowNodeId)
319 {
320 if (connection == nullptr) {
321 return VSYNC_ERROR_NULLPTR;
322 }
323 std::lock_guard<std::mutex> locker(mutex_);
324 int32_t proxyPid = connection->proxyPid_;
325 if (connectionCounter_[proxyPid] > VSYNC_CONNECTION_MAX_SIZE) {
326 VLOGE("You [%{public}d] have created too many vsync connection, please check!!!", proxyPid);
327 return VSYNC_ERROR_API_FAILED;
328 }
329 auto it = std::find(connections_.begin(), connections_.end(), connection);
330 if (it != connections_.end()) {
331 return VSYNC_ERROR_INVALID_ARGUMENTS;
332 }
333 RS_TRACE_NAME_FMT("Add VSyncConnection: %s", connection->info_.name_.c_str());
334 connections_.push_back(connection);
335 connectionCounter_[proxyPid]++;
336 if (windowNodeId != 0) {
337 connectionsMap_[windowNodeId].push_back(connection);
338 } else {
339 uint32_t tmpPid;
340 if (QosGetPidByName(connection->info_.name_, tmpPid) == VSYNC_ERROR_OK) {
341 connectionsMap_[tmpPid].push_back(connection);
342 }
343 }
344
345 return VSYNC_ERROR_OK;
346 }
347
RemoveConnection(const sptr<VSyncConnection> & connection)348 VsyncError VSyncDistributor::RemoveConnection(const sptr<VSyncConnection>& connection)
349 {
350 if (connection == nullptr) {
351 return VSYNC_ERROR_NULLPTR;
352 }
353 std::lock_guard<std::mutex> locker(mutex_);
354 int32_t proxyPid = connection->proxyPid_;
355 auto it = std::find(connections_.begin(), connections_.end(), connection);
356 if (it == connections_.end()) {
357 return VSYNC_ERROR_INVALID_ARGUMENTS;
358 }
359 RS_TRACE_NAME_FMT("Remove VSyncConnection: %s", connection->info_.name_.c_str());
360 connections_.erase(it);
361 connectionCounter_[proxyPid]--;
362 if (connectionCounter_[proxyPid] == 0) {
363 connectionCounter_.erase(proxyPid);
364 }
365 connectionsMap_.erase(connection->windowNodeId_);
366 uint32_t tmpPid;
367 if (QosGetPidByName(connection->info_.name_, tmpPid) == VSYNC_ERROR_OK) {
368 auto iter = connectionsMap_.find(tmpPid);
369 if (iter == connectionsMap_.end()) {
370 return VSYNC_ERROR_OK;
371 }
372 auto connIter = find(iter->second.begin(), iter->second.end(), connection);
373 if (connIter != iter->second.end()) {
374 iter->second.erase(connIter);
375 }
376 if (iter->second.empty()) {
377 connectionsMap_.erase(iter);
378 }
379 }
380 return VSYNC_ERROR_OK;
381 }
382
WaitForVsyncOrRequest(std::unique_lock<std::mutex> & locker)383 void VSyncDistributor::WaitForVsyncOrRequest(std::unique_lock<std::mutex> &locker)
384 {
385 if (!vsyncThreadRunning_) {
386 return;
387 }
388
389 // before con_ wait, notify the rnv_con.
390 #if defined(RS_ENABLE_DVSYNC)
391 dvsync_->RNVNotify();
392 if (!isRs_ && IsDVsyncOn()) {
393 con_.wait_for(locker, std::chrono::nanoseconds(dvsync_->WaitTime()), [this] { return dvsync_->WaitCond(); });
394 } else {
395 if (!(hasVsync_.load() && isRs_)) {
396 con_.wait(locker);
397 }
398 hasVsync_.store(false);
399 }
400 if (pendingRNVInVsync_) {
401 return;
402 }
403 if (IsDVsyncOn()) {
404 std::pair<bool, int64_t> result = dvsync_->DoPreExecute(locker, con_);
405 if (result.first) {
406 event_.timestamp = result.second;
407 lastDVsyncTS_.store(result.second);
408 event_.vsyncCount++;
409 if (vsyncEnabled_ == false) {
410 ScopedBytrace func(name_ + "_EnableVsync");
411 EnableVSync();
412 }
413 }
414 }
415 #else
416 con_.wait(locker);
417 #endif
418 }
419
Now()420 int64_t Now()
421 {
422 const auto &now = std::chrono::steady_clock::now().time_since_epoch();
423 return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
424 }
425
WaitForVsyncOrTimeOut(std::unique_lock<std::mutex> & locker)426 void VSyncDistributor::WaitForVsyncOrTimeOut(std::unique_lock<std::mutex> &locker)
427 {
428 #if defined(RS_ENABLE_DVSYNC)
429 dvsync_->RNVNotify();
430 #endif
431 if (con_.wait_for(locker, std::chrono::milliseconds(SOFT_VSYNC_PERIOD)) ==
432 std::cv_status::timeout) {
433 event_.timestamp = Now();
434 event_.vsyncCount++;
435 }
436 }
437
ThreadMain()438 void VSyncDistributor::ThreadMain()
439 {
440 // set thread priorty
441 setpriority(PRIO_PROCESS, 0, THREAD_PRIORTY);
442 struct sched_param param = {0};
443 param.sched_priority = SCHED_PRIORITY;
444 sched_setscheduler(0, SCHED_FIFO, ¶m);
445
446 #ifdef COMPOSER_SCHED_ENABLE
447 std::string threadName = "VSync-" + name_;
448 SubScribeSystemAbility(threadName);
449 #endif
450
451 int64_t timestamp;
452 while (vsyncThreadRunning_ == true) {
453 std::vector<sptr<VSyncConnection>> conns;
454 {
455 bool waitForVSync = false;
456 std::unique_lock<std::mutex> locker(mutex_);
457 CollectConns(waitForVSync, timestamp, conns, true);
458 // no vsync signal
459 if (timestamp == 0) {
460 // there is some connections request next vsync, enable vsync if vsync disable and
461 // and start the software vsync with wait_for function
462 if (waitForVSync == true && vsyncEnabled_ == false) {
463 EnableVSync();
464 WaitForVsyncOrTimeOut(locker);
465 } else {
466 // just wait request or vsync signal
467 WaitForVsyncOrRequest(locker);
468 }
469 RS_TRACE_NAME_FMT("%s_continue: waitForVSync %d, vsyncEnabled %d, dvsyncOn %d",
470 name_.c_str(), waitForVSync, vsyncEnabled_, IsDVsyncOn());
471 if ((isRs_ && event_.timestamp == 0) || !IsDVsyncOn()) {
472 continue;
473 } else {
474 timestamp = event_.timestamp;
475 }
476 } else if ((timestamp > 0) && (waitForVSync == false) && (isRs_ || !IsDVsyncOn())) {
477 // if there is a vsync signal but no vaild connections, we should disable vsync
478 RS_TRACE_NAME_FMT("%s_DisableVSync, there is no valid connections", name_.c_str());
479 DisableVSync();
480 continue;
481 }
482 }
483 if (!PostVSyncEventPreProcess(timestamp, conns)) {
484 continue;
485 } else {
486 // IMPORTANT: ScopedDebugTrace here will cause frame loss.
487 RS_TRACE_NAME_FMT("%s_SendVsync", name_.c_str());
488 }
489 PostVSyncEvent(conns, timestamp, true);
490 }
491 }
492
CollectConns(bool & waitForVSync,int64_t & timestamp,std::vector<sptr<VSyncConnection>> & conns,bool isDvsyncThread)493 void VSyncDistributor::CollectConns(bool &waitForVSync, int64_t ×tamp,
494 std::vector<sptr<VSyncConnection>> &conns, bool isDvsyncThread)
495 {
496 if (isDvsyncThread) {
497 timestamp = event_.timestamp;
498 event_.timestamp = 0;
499 }
500 if (vsyncMode_ == VSYNC_MODE_LTPO) {
501 CollectConnectionsLTPO(waitForVSync, timestamp, conns, event_.vsyncPulseCount, isDvsyncThread);
502 } else {
503 CollectConnections(waitForVSync, timestamp, conns, event_.vsyncCount, isDvsyncThread);
504 }
505 }
506
PostVSyncEventPreProcess(int64_t & timestamp,std::vector<sptr<VSyncConnection>> & conns)507 bool VSyncDistributor::PostVSyncEventPreProcess(int64_t ×tamp, std::vector<sptr<VSyncConnection>> &conns)
508 {
509 #if defined(RS_ENABLE_DVSYNC)
510 bool waitForVSync = false;
511 // ensure the preexecution only gets ahead for at most one period(i.e., 3 buffer rotation)
512 if (IsDVsyncOn()) {
513 {
514 std::unique_lock<std::mutex> locker(mutex_);
515 dvsync_->MarkDistributorSleep(true);
516 dvsync_->RNVNotify();
517 dvsync_->DelayBeforePostEvent(event_.timestamp, locker);
518 dvsync_->MarkDistributorSleep(false);
519 CollectConns(waitForVSync, timestamp, conns, true);
520 hasVsync_.store(false);
521 }
522 // if getting switched into vsync mode after sleep
523 if (!IsDVsyncOn()) {
524 ScopedBytrace func("NoAccumulateInVsync");
525 lastDVsyncTS_.store(0); // ensure further OnVSyncEvent do not skip
526 for (auto conn : conns) {
527 RequestNextVSync(conn);
528 } // resend RNV for vsync
529 return false; // do not accumulate frame;
530 }
531 } else {
532 std::unique_lock<std::mutex> locker(mutex_);
533 hasVsync_.store(false);
534 }
535 {
536 std::unique_lock<std::mutex> locker(mutex_);
537 pendingRNVInVsync_ = false;
538 if (IsUiDvsyncOn()) {
539 event_.period = dvsync_->GetPeriod();
540 }
541 }
542 #endif
543 return true;
544 }
545
EnableVSync()546 void VSyncDistributor::EnableVSync()
547 {
548 if (controller_ != nullptr && vsyncEnabled_ == false) {
549 controller_->SetCallback(this);
550 controller_->SetEnable(true, vsyncEnabled_);
551 #if defined(RS_ENABLE_DVSYNC)
552 dvsync_->RecordEnableVsync();
553 #endif
554 }
555 }
556
DisableVSync()557 void VSyncDistributor::DisableVSync()
558 {
559 if (controller_ != nullptr && vsyncEnabled_ == true) {
560 controller_->SetEnable(false, vsyncEnabled_);
561 }
562 }
563
564 #if defined(RS_ENABLE_DVSYNC)
OnDVSyncTrigger(int64_t now,int64_t period,uint32_t refreshRate,VSyncMode vsyncMode)565 void VSyncDistributor::OnDVSyncTrigger(int64_t now, int64_t period, uint32_t refreshRate, VSyncMode vsyncMode)
566 {
567 std::unique_lock<std::mutex> locker(mutex_);
568 vsyncMode_ = vsyncMode;
569 dvsync_->RuntimeSwitch();
570 if (IsDVsyncOn()) {
571 RS_TRACE_NAME_FMT("VSyncD onVSyncEvent, now:%ld", now);
572 } else {
573 RS_TRACE_NAME_FMT("VSync onVSyncEvent, now:%ld", now);
574 }
575 event_.period = period;
576
577 dvsync_->RecordVSync(now, period, refreshRate);
578 dvsync_->NotifyPreexecuteWait();
579
580 SendConnectionsToVSyncWindow(now, period, refreshRate, vsyncMode, locker);
581 // when dvsync switch to vsync, skip all vsync events within one period from the pre-rendered timestamp
582 if (dvsync_->NeedSkipDVsyncPrerenderedFrame()) {
583 return;
584 }
585
586 // When vsync switches to dvsync, need to handle pending RNVs during vsync
587 if (!IsDVsyncOn() || pendingRNVInVsync_) {
588 event_.timestamp = now;
589 event_.vsyncCount++;
590 }
591
592 if (refreshRate > 0) {
593 event_.vsyncPulseCount += static_cast<int64_t>(VSYNC_MAX_REFRESHRATE / refreshRate);
594 generatorRefreshRate_ = refreshRate;
595 }
596
597 ChangeConnsRateLocked();
598 RS_TRACE_NAME_FMT("pendingRNVInVsync: %d DVSyncOn: %d isRS:%d", pendingRNVInVsync_, IsDVsyncOn(), isRs_);
599 if (dvsync_->WaitCond() || pendingRNVInVsync_) {
600 con_.notify_all();
601 } else {
602 CheckNeedDisableDvsync(now, period);
603 }
604 }
605 #endif
606
OnVSyncTrigger(int64_t now,int64_t period,uint32_t refreshRate,VSyncMode vsyncMode)607 void VSyncDistributor::OnVSyncTrigger(int64_t now, int64_t period, uint32_t refreshRate, VSyncMode vsyncMode)
608 {
609 std::vector<sptr<VSyncConnection>> conns;
610 uint32_t generatorRefreshRate;
611 int64_t vsyncCount;
612
613 {
614 bool waitForVSync = false;
615 std::lock_guard<std::mutex> locker(mutex_);
616 event_.vsyncCount++;
617 vsyncCount = event_.vsyncCount;
618
619 if (refreshRate > 0) {
620 event_.vsyncPulseCount += static_cast<int64_t>(VSYNC_MAX_REFRESHRATE / refreshRate);
621 generatorRefreshRate_ = refreshRate;
622 }
623 vsyncMode_ = vsyncMode;
624 ChangeConnsRateLocked();
625
626 if (vsyncMode_ == VSYNC_MODE_LTPO) {
627 CollectConnectionsLTPO(waitForVSync, now, conns, event_.vsyncPulseCount);
628 } else {
629 CollectConnections(waitForVSync, now, conns, event_.vsyncCount);
630 }
631 if (!waitForVSync) {
632 DisableVSync();
633 return;
634 }
635
636 countTraceValue_ = (countTraceValue_ + 1) % 2; // 2 : change num
637 CountTrace(HITRACE_TAG_GRAPHIC_AGP, "VSync-" + name_, countTraceValue_);
638
639 generatorRefreshRate = generatorRefreshRate_;
640 }
641
642 for (uint32_t i = 0; i < conns.size(); i++) {
643 int64_t actualPeriod = period;
644 if ((generatorRefreshRate > 0) && (conns[i]->refreshRate_ > 0) &&
645 (generatorRefreshRate % conns[i]->refreshRate_ == 0)) {
646 actualPeriod = period * static_cast<int64_t>(generatorRefreshRate / conns[i]->refreshRate_);
647 }
648 int32_t ret = conns[i]->PostEvent(now, actualPeriod, vsyncCount);
649 VLOGD("Distributor name:%{public}s, connection name:%{public}s, ret:%{public}d",
650 name_.c_str(), conns[i]->info_.name.c_str(), ret);
651 if (ret == 0 || ret == ERRNO_OTHER) {
652 RemoveConnection(conns[i]);
653 } else if (ret == ERRNO_EAGAIN) {
654 std::lock_guard<std::mutex> locker(mutex_);
655 // Trigger VSync Again for LTPO
656 conns[i]->triggerThisTime_ = true;
657 // Exclude SetVSyncRate for LTPS
658 if (conns[i]->rate_ < 0) {
659 conns[i]->rate_ = 0;
660 }
661 }
662 }
663 }
664
OnVSyncEvent(int64_t now,int64_t period,uint32_t refreshRate,VSyncMode vsyncMode)665 void VSyncDistributor::OnVSyncEvent(int64_t now, int64_t period, uint32_t refreshRate, VSyncMode vsyncMode)
666 {
667 #if defined(RS_ENABLE_DVSYNC)
668 if (dvsync_->IsFeatureEnabled()) {
669 OnDVSyncTrigger(now, period, refreshRate, vsyncMode);
670 } else
671 #endif
672 {
673 OnVSyncTrigger(now, period, refreshRate, vsyncMode);
674 }
675 }
676
677 #if defined(RS_ENABLE_DVSYNC)
SendConnectionsToVSyncWindow(int64_t now,int64_t period,uint32_t refreshRate,VSyncMode vsyncMode,std::unique_lock<std::mutex> & locker)678 void VSyncDistributor::SendConnectionsToVSyncWindow(int64_t now, int64_t period, uint32_t refreshRate,
679 VSyncMode vsyncMode, std::unique_lock<std::mutex> &locker)
680 {
681 std::vector<sptr<VSyncConnection>> conns;
682 bool waitForVSync = false;
683 if (isRs_ || GetUIDVsyncPid() == 0) {
684 return;
685 }
686 CollectConns(waitForVSync, now, conns, false);
687 locker.unlock();
688 PostVSyncEvent(conns, now, false);
689 locker.lock();
690 }
691
GetUIDVsyncPid()692 int32_t VSyncDistributor::GetUIDVsyncPid()
693 {
694 int32_t pid = 0;
695 if (!isRs_) {
696 pid = dvsync_->GetProxyPid();
697 }
698 return pid;
699 }
700 #endif
701
CheckNeedDisableDvsync(int64_t now,int64_t period)702 void VSyncDistributor::CheckNeedDisableDvsync(int64_t now, int64_t period)
703 {
704 #if defined(RS_ENABLE_DVSYNC)
705 if (!isRs_ && IsDVsyncOn()) {
706 return;
707 }
708 // When Dvsync on, if the RequestNextVsync is not invoked within three period and SetVSyncRate
709 // is not invoked either, execute DisableVSync.
710 for (uint32_t i = 0; i < connections_.size(); i++) {
711 if (connections_[i]->triggerThisTime_ || connections_[i]->rate_ >= 0) {
712 return;
713 }
714 }
715 if (now - dvsync_->GetLastRnvTS() > 3 * period) { // 3 period
716 ScopedBytrace func(name_ + "_DisableVsync");
717 DisableVSync();
718 }
719 #endif
720 }
721
722 /* std::pair<id, refresh rate> */
OnConnsRefreshRateChanged(const std::vector<std::pair<uint64_t,uint32_t>> & refreshRates)723 void VSyncDistributor::OnConnsRefreshRateChanged(const std::vector<std::pair<uint64_t, uint32_t>> &refreshRates)
724 {
725 std::lock_guard<std::mutex> locker(changingConnsRefreshRatesMtx_);
726 for (auto refreshRate : refreshRates) {
727 bool found = false;
728 for (auto it = changingConnsRefreshRates_.begin(); it != changingConnsRefreshRates_.end(); it++) {
729 if ((*it).first == refreshRate.first) { // first is linkerId
730 (*it).second = refreshRate.second; // second is refreshRate
731 found = true;
732 break;
733 }
734 }
735 if (!found) {
736 changingConnsRefreshRates_.push_back(refreshRate);
737 }
738 }
739 }
740
SubScribeSystemAbility(const std::string & threadName)741 void VSyncDistributor::SubScribeSystemAbility(const std::string& threadName)
742 {
743 VLOGI("%{public}s", __func__);
744 sptr<ISystemAbilityManager> systemAbilityManager =
745 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
746 if (!systemAbilityManager) {
747 VLOGE("%{public}s failed to get system ability manager client", __func__);
748 return;
749 }
750 std::string strUid = std::to_string(getuid());
751 std::string strPid = std::to_string(getpid());
752 std::string strTid = std::to_string(gettid());
753
754 saStatusChangeListener_ = new (std::nothrow)VSyncSystemAbilityListener(threadName, strUid, strPid, strTid);
755 int32_t ret = systemAbilityManager->SubscribeSystemAbility(RES_SCHED_SYS_ABILITY_ID, saStatusChangeListener_);
756 if (ret != ERR_OK) {
757 VLOGE("%{public}s subscribe system ability %{public}d failed.", __func__, RES_SCHED_SYS_ABILITY_ID);
758 saStatusChangeListener_ = nullptr;
759 }
760 }
761
CollectConnections(bool & waitForVSync,int64_t timestamp,std::vector<sptr<VSyncConnection>> & conns,int64_t vsyncCount,bool isDvsyncThread)762 void VSyncDistributor::CollectConnections(bool &waitForVSync, int64_t timestamp,
763 std::vector<sptr<VSyncConnection>> &conns, int64_t vsyncCount, bool isDvsyncThread)
764 {
765 #if defined(RS_ENABLE_DVSYNC)
766 auto uiDVsyncPid = GetUIDVsyncPid();
767 #endif
768 for (uint32_t i = 0; i < connections_.size(); i++) {
769 #if defined(RS_ENABLE_DVSYNC)
770 if (uiDVsyncPid != 0 && ((!isDvsyncThread && connections_[i]->proxyPid_ == uiDVsyncPid) ||
771 (isDvsyncThread && connections_[i]->proxyPid_ != uiDVsyncPid))) {
772 continue;
773 }
774 #endif
775 int32_t rate = connections_[i]->highPriorityState_ ? connections_[i]->highPriorityRate_ :
776 connections_[i]->rate_;
777
778 if (rate < 0) {
779 continue;
780 }
781
782 if (rate == 0) { // for RequestNextVSync
783 waitForVSync = true;
784 if (timestamp > 0) {
785 connections_[i]->rate_ = -1;
786 connections_[i]->triggerThisTime_ = false;
787 conns.push_back(connections_[i]);
788 }
789 continue;
790 }
791
792 RS_TRACE_NAME_FMT("CollectConnections name:%s, proxyPid:%d, highPriorityState_:%d, highPriorityRate_:%d"
793 ", rate_:%d, timestamp:%ld, vsyncCount:%ld", connections_[i]->info_.name_.c_str(),
794 connections_[i]->proxyPid_, connections_[i]->highPriorityState_,
795 connections_[i]->highPriorityRate_, connections_[i]->rate_, timestamp, vsyncCount);
796
797 if (connections_[i]->rate_ == 0) { // for SetHighPriorityVSyncRate with RequestNextVSync
798 waitForVSync = true;
799 if (timestamp > 0 && (vsyncCount % rate == 0)) {
800 connections_[i]->rate_ = -1;
801 connections_[i]->triggerThisTime_ = false;
802 conns.push_back(connections_[i]);
803 }
804 } else if (connections_[i]->rate_ > 0) { // for SetVSyncRate
805 waitForVSync = true;
806 if (timestamp > 0 && (vsyncCount % rate == 0)) {
807 conns.push_back(connections_[i]);
808 }
809 }
810 }
811 }
812
CollectConnectionsLTPO(bool & waitForVSync,int64_t timestamp,std::vector<sptr<VSyncConnection>> & conns,int64_t vsyncCount,bool isDvsyncThread)813 void VSyncDistributor::CollectConnectionsLTPO(bool &waitForVSync, int64_t timestamp,
814 std::vector<sptr<VSyncConnection>> &conns, int64_t vsyncCount, bool isDvsyncThread)
815 {
816 #if defined(RS_ENABLE_DVSYNC)
817 auto uiDVsyncPid = GetUIDVsyncPid();
818 #endif
819 for (uint32_t i = 0; i < connections_.size(); i++) {
820 #if defined(RS_ENABLE_DVSYNC)
821 if (uiDVsyncPid != 0 && ((!isDvsyncThread && connections_[i]->proxyPid_ == uiDVsyncPid) ||
822 (isDvsyncThread && connections_[i]->proxyPid_ != uiDVsyncPid))) {
823 continue;
824 }
825 #endif
826 SCOPED_DEBUG_TRACE_FMT("CollectConnectionsLTPO, i:%d, name:%s, rate:%d, vsyncPulseFreq:%u"
827 ", referencePulseCount:%ld, vsyncCount:%d", i, connections_[i]->info_.name_.c_str(), connections_[i]->rate_,
828 connections_[i]->vsyncPulseFreq_, connections_[i]->referencePulseCount_, vsyncCount);
829 if (!connections_[i]->triggerThisTime_ && connections_[i]->rate_ <= 0) {
830 continue;
831 }
832 waitForVSync = true;
833 if (timestamp <= 0) {
834 break;
835 }
836 int64_t vsyncPulseFreq = static_cast<int64_t>(connections_[i]->vsyncPulseFreq_);
837 if ((vsyncCount - connections_[i]->referencePulseCount_) % vsyncPulseFreq == 0) {
838 connections_[i]->triggerThisTime_ = false;
839 if (connections_[i]->rate_ == 0) {
840 connections_[i]->rate_ = -1;
841 }
842 conns.push_back(connections_[i]);
843 }
844 }
845 }
846
PostVSyncEvent(const std::vector<sptr<VSyncConnection>> & conns,int64_t timestamp,bool isDvsyncThread)847 void VSyncDistributor::PostVSyncEvent(const std::vector<sptr<VSyncConnection>> &conns,
848 int64_t timestamp, bool isDvsyncThread)
849 {
850 #if defined(RS_ENABLE_DVSYNC)
851 if (isDvsyncThread) {
852 std::unique_lock<std::mutex> locker(mutex_);
853 dvsync_->RecordPostEvent(conns, timestamp);
854 }
855 #endif
856 uint32_t generatorRefreshRate = 0;
857 int64_t eventPeriod = 0;
858 int64_t vsyncCount = 0;
859 {
860 std::unique_lock<std::mutex> locker(mutex_);
861 generatorRefreshRate = generatorRefreshRate_;
862 eventPeriod = event_.period;
863 vsyncCount = event_.vsyncCount;
864 }
865 for (uint32_t i = 0; i < conns.size(); i++) {
866 int64_t period = eventPeriod;
867 if ((generatorRefreshRate > 0) && (conns[i]->refreshRate_ > 0) &&
868 (generatorRefreshRate % conns[i]->refreshRate_ == 0)) {
869 period = eventPeriod * static_cast<int64_t>(generatorRefreshRate / conns[i]->refreshRate_);
870 }
871 int32_t ret = conns[i]->PostEvent(timestamp, period, vsyncCount);
872 VLOGD("Distributor name:%{public}s, connection name:%{public}s, ret:%{public}d",
873 name_.c_str(), conns[i]->info_.name_.c_str(), ret);
874 if (ret == 0 || ret == ERRNO_OTHER) {
875 RemoveConnection(conns[i]);
876 } else if (ret == ERRNO_EAGAIN) {
877 std::unique_lock<std::mutex> locker(mutex_);
878 // Trigger VSync Again for LTPO
879 conns[i]->triggerThisTime_ = true;
880 #if defined(RS_ENABLE_DVSYNC)
881 if (isDvsyncThread) {
882 hasVsync_.store(true);
883 }
884 #endif
885 // Exclude SetVSyncRate for LTPS
886 if (conns[i]->rate_ < 0) {
887 conns[i]->rate_ = 0;
888 }
889 }
890 }
891 }
892
RequestNextVSync(const sptr<VSyncConnection> & connection,const std::string & fromWhom,int64_t lastVSyncTS)893 VsyncError VSyncDistributor::RequestNextVSync(const sptr<VSyncConnection> &connection, const std::string &fromWhom,
894 int64_t lastVSyncTS)
895 {
896 if (connection == nullptr) {
897 VLOGE("connection is nullptr");
898 return VSYNC_ERROR_NULLPTR;
899 }
900
901 ScopedBytrace func(connection->info_.name_ + "_RequestNextVSync");
902 std::unique_lock<std::mutex> locker(mutex_);
903
904 #if defined(RS_ENABLE_DVSYNC)
905 if (IsDVsyncOn() && isRs_) {
906 dvsync_->RNVWait(locker);
907 }
908 #endif
909
910 auto it = find(connections_.begin(), connections_.end(), connection);
911 if (it == connections_.end()) {
912 VLOGE("connection is invalid arguments");
913 #if defined(RS_ENABLE_DVSYNC)
914 if (IsDVsyncOn()) {
915 dvsync_->RNVNotify();
916 }
917 #endif
918 return VSYNC_ERROR_INVALID_ARGUMENTS;
919 }
920 // record RNV and lastVSyncTS for D-VSYNC
921 #if defined(RS_ENABLE_DVSYNC)
922 dvsync_->RecordRNV(connection, fromWhom, lastVSyncTS);
923 if (!IsDVsyncOn()) {
924 pendingRNVInVsync_ = true;
925 }
926 #endif
927 if (connection->rate_ < 0) {
928 connection->rate_ = 0;
929 }
930 connection->triggerThisTime_ = true;
931 #if defined(RS_ENABLE_DVSYNC)
932 hasVsync_.store(true);
933 if (dvsync_->IsFeatureEnabled()) {
934 con_.notify_all();
935 } else
936 #endif
937 {
938 EnableVSync();
939 }
940 VLOGD("conn name:%{public}s, rate:%{public}d", connection->info_.name_.c_str(), connection->rate_);
941 return VSYNC_ERROR_OK;
942 }
943
SetVSyncRate(int32_t rate,const sptr<VSyncConnection> & connection)944 VsyncError VSyncDistributor::SetVSyncRate(int32_t rate, const sptr<VSyncConnection>& connection)
945 {
946 if (rate < -1 || connection == nullptr) {
947 return VSYNC_ERROR_INVALID_ARGUMENTS;
948 }
949 std::lock_guard<std::mutex> locker(mutex_);
950 auto it = find(connections_.begin(), connections_.end(), connection);
951 if (it == connections_.end()) {
952 return VSYNC_ERROR_INVALID_ARGUMENTS;
953 }
954 if (connection->rate_ == rate) {
955 return VSYNC_ERROR_INVALID_ARGUMENTS;
956 }
957 connection->rate_ = rate;
958 VLOGD("conn name:%{public}s", connection->info_.name_.c_str());
959 #if defined(RS_ENABLE_DVSYNC)
960 if (dvsync_->IsFeatureEnabled()) {
961 con_.notify_all();
962 } else
963 #endif
964 {
965 EnableVSync();
966 }
967 return VSYNC_ERROR_OK;
968 }
969
SetHighPriorityVSyncRate(int32_t highPriorityRate,const sptr<VSyncConnection> & connection)970 VsyncError VSyncDistributor::SetHighPriorityVSyncRate(int32_t highPriorityRate, const sptr<VSyncConnection>& connection)
971 {
972 if (highPriorityRate <= 0 || connection == nullptr) {
973 return VSYNC_ERROR_INVALID_ARGUMENTS;
974 }
975
976 std::lock_guard<std::mutex> locker(mutex_);
977 auto it = find(connections_.begin(), connections_.end(), connection);
978 if (it == connections_.end()) {
979 return VSYNC_ERROR_INVALID_ARGUMENTS;
980 }
981 if (connection->highPriorityRate_ == highPriorityRate) {
982 return VSYNC_ERROR_INVALID_ARGUMENTS;
983 }
984 connection->highPriorityRate_ = highPriorityRate;
985 connection->highPriorityState_ = true;
986 VLOGD("in, conn name:%{public}s, highPriorityRate:%{public}d", connection->info_.name_.c_str(),
987 connection->highPriorityRate_);
988 #if defined(RS_ENABLE_DVSYNC)
989 if (dvsync_->IsFeatureEnabled()) {
990 con_.notify_all();
991 } else
992 #endif
993 {
994 EnableVSync();
995 }
996 return VSYNC_ERROR_OK;
997 }
998
QosGetPidByName(const std::string & name,uint32_t & pid)999 VsyncError VSyncDistributor::QosGetPidByName(const std::string& name, uint32_t& pid)
1000 {
1001 if (name.find("WM") == std::string::npos && name.find("ArkWebCore") == std::string::npos
1002 && name.find("NWeb") == std::string::npos) {
1003 return VSYNC_ERROR_INVALID_ARGUMENTS;
1004 }
1005 std::string::size_type pos = name.find("_");
1006 if (pos == std::string::npos) {
1007 return VSYNC_ERROR_INVALID_ARGUMENTS;
1008 }
1009 pid = (uint32_t)stoi(name.substr(pos + 1));
1010 return VSYNC_ERROR_OK;
1011 }
1012
SetQosVSyncRateByPid(uint32_t pid,int32_t rate,bool isSystemAnimateScene)1013 VsyncError VSyncDistributor::SetQosVSyncRateByPid(uint32_t pid, int32_t rate, bool isSystemAnimateScene)
1014 {
1015 // only set vsync rate by pid in SystemAnimateSecne
1016 if (!isSystemAnimateScene && rate != DEFAULT_VSYNC_RATE) {
1017 return VSYNC_ERROR_OK;
1018 }
1019 auto iter = connectionsMap_.find(pid);
1020 if (iter == connectionsMap_.end()) {
1021 VLOGD("%{public}s:%{public}d pid[%{public}u] can not found", __func__, __LINE__, pid);
1022 return VSYNC_ERROR_INVALID_ARGUMENTS;
1023 }
1024 bool isNeedNotify = false;
1025 for (auto connection : iter->second) {
1026 uint32_t tmpPid;
1027 if (QosGetPidByName(connection->info_.name_, tmpPid) != VSYNC_ERROR_OK || tmpPid != pid) {
1028 continue;
1029 }
1030 if (connection->highPriorityRate_ != rate) {
1031 connection->highPriorityRate_ = rate;
1032 connection->highPriorityState_ = true;
1033 VLOGD("in, conn name:%{public}s, highPriorityRate:%{public}d", connection->info_.name_.c_str(),
1034 connection->highPriorityRate_);
1035 isNeedNotify = true;
1036 }
1037 }
1038 if (isNeedNotify) {
1039 #if defined(RS_ENABLE_DVSYNC)
1040 if (dvsync_->IsFeatureEnabled()) {
1041 con_.notify_all();
1042 } else
1043 #endif
1044 {
1045 EnableVSync();
1046 }
1047 }
1048 return VSYNC_ERROR_OK;
1049 }
1050
ExtractPid(uint64_t id)1051 constexpr pid_t VSyncDistributor::ExtractPid(uint64_t id)
1052 {
1053 constexpr uint32_t bits = 32u;
1054 return static_cast<pid_t>(id >> bits);
1055 }
1056
SetQosVSyncRate(uint64_t windowNodeId,int32_t rate,bool isSystemAnimateScene)1057 VsyncError VSyncDistributor::SetQosVSyncRate(uint64_t windowNodeId, int32_t rate, bool isSystemAnimateScene)
1058 {
1059 std::lock_guard<std::mutex> locker(mutex_);
1060 VsyncError resCode = SetQosVSyncRateByPid(ExtractPid(windowNodeId), rate, isSystemAnimateScene);
1061 auto iter = connectionsMap_.find(windowNodeId);
1062 if (iter == connectionsMap_.end()) {
1063 return resCode;
1064 }
1065
1066 bool isNeedNotify = false;
1067 for (auto& connection : iter->second) {
1068 if (connection && connection->highPriorityRate_ != rate) {
1069 connection->highPriorityRate_ = rate;
1070 connection->highPriorityState_ = true;
1071 VLOGD("in, conn name:%{public}s, highPriorityRate:%{public}d", connection->info_.name_.c_str(),
1072 connection->highPriorityRate_);
1073 isNeedNotify = true;
1074 }
1075 }
1076 if (isNeedNotify) {
1077 #if defined(RS_ENABLE_DVSYNC)
1078 if (dvsync_->IsFeatureEnabled()) {
1079 con_.notify_all();
1080 } else
1081 #endif
1082 {
1083 EnableVSync();
1084 }
1085 }
1086 return VSYNC_ERROR_OK;
1087 }
1088
ChangeConnsRateLocked()1089 void VSyncDistributor::ChangeConnsRateLocked()
1090 {
1091 std::lock_guard<std::mutex> locker(changingConnsRefreshRatesMtx_);
1092 for (auto connRefreshRate : changingConnsRefreshRates_) {
1093 for (auto conn : connections_) {
1094 if (conn->id_ != connRefreshRate.first) {
1095 continue;
1096 }
1097 uint32_t refreshRate = connRefreshRate.second;
1098 if ((generatorRefreshRate_ == 0) || (refreshRate == 0) ||
1099 (VSYNC_MAX_REFRESHRATE % refreshRate != 0) || (generatorRefreshRate_ % refreshRate != 0)) {
1100 conn->refreshRate_ = 0;
1101 conn->vsyncPulseFreq_ = 1;
1102 continue;
1103 }
1104 conn->refreshRate_ = refreshRate;
1105 conn->vsyncPulseFreq_ = VSYNC_MAX_REFRESHRATE / refreshRate;
1106 conn->referencePulseCount_ = event_.vsyncPulseCount;
1107 }
1108 }
1109 changingConnsRefreshRates_.clear();
1110 }
1111
IsDVsyncOn()1112 bool VSyncDistributor::IsDVsyncOn()
1113 {
1114 #if defined(RS_ENABLE_DVSYNC)
1115 return dvsync_->IsEnabledAndOn();
1116 #else
1117 return false;
1118 #endif
1119 }
1120
SetFrameIsRender(bool isRender)1121 void VSyncDistributor::SetFrameIsRender(bool isRender)
1122 {
1123 #if defined(RS_ENABLE_DVSYNC)
1124 std::unique_lock<std::mutex> locker(mutex_);
1125 ScopedBytrace trace("SetFrameIsRender:" + std::to_string(isRender));
1126 if (isRender) {
1127 dvsync_->UnMarkRSNotRendering();
1128 } else {
1129 dvsync_->MarkRSNotRendering();
1130 }
1131 #endif
1132 }
1133
MarkRSAnimate()1134 void VSyncDistributor::MarkRSAnimate()
1135 {
1136 #if defined(RS_ENABLE_DVSYNC)
1137 dvsync_->MarkRSAnimate();
1138 #endif
1139 }
1140
UnmarkRSAnimate()1141 void VSyncDistributor::UnmarkRSAnimate()
1142 {
1143 #if defined(RS_ENABLE_DVSYNC)
1144 dvsync_->UnmarkRSAnimate();
1145 #endif
1146 }
1147
HasPendingUIRNV()1148 bool VSyncDistributor::HasPendingUIRNV()
1149 {
1150 #if defined(RS_ENABLE_DVSYNC)
1151 return dvsync_->HasPendingUIRNV();
1152 #else
1153 return false;
1154 #endif
1155 }
1156
SetUiDvsyncSwitch(bool dvsyncSwitch,const sptr<VSyncConnection> & connection)1157 VsyncError VSyncDistributor::SetUiDvsyncSwitch(bool dvsyncSwitch, const sptr<VSyncConnection> &connection)
1158 {
1159 #if defined(RS_ENABLE_DVSYNC)
1160 std::lock_guard<std::mutex> locker(mutex_);
1161 if (dvsyncSwitch) {
1162 dvsync_->RuntimeMark(connection);
1163 } else {
1164 dvsync_->RuntimeMark(nullptr);
1165 }
1166 #endif
1167 return VSYNC_ERROR_OK;
1168 }
1169
SetUiDvsyncConfig(int32_t bufferCount)1170 VsyncError VSyncDistributor::SetUiDvsyncConfig(int32_t bufferCount)
1171 {
1172 #if defined(RS_ENABLE_DVSYNC)
1173 std::lock_guard<std::mutex> locker(mutex_);
1174 dvsync_->SetUiDvsyncConfig(bufferCount);
1175 #endif
1176 return VSYNC_ERROR_OK;
1177 }
1178
GetRefreshRate()1179 uint32_t VSyncDistributor::GetRefreshRate()
1180 {
1181 #if defined(RS_ENABLE_DVSYNC)
1182 std::lock_guard<std::mutex> locker(mutex_);
1183 return dvsync_->GetRefreshRate();
1184 #else
1185 return generatorRefreshRate_;
1186 #endif
1187 }
1188
RecordVsyncModeChange(uint32_t refreshRate,int64_t period)1189 void VSyncDistributor::RecordVsyncModeChange(uint32_t refreshRate, int64_t period)
1190 {
1191 #if defined(RS_ENABLE_DVSYNC)
1192 std::lock_guard<std::mutex> locker(mutex_);
1193 dvsync_->RecordVsyncModeChange(refreshRate, period);
1194 #endif
1195 }
1196
IsUiDvsyncOn()1197 bool VSyncDistributor::IsUiDvsyncOn()
1198 {
1199 #if defined(RS_ENABLE_DVSYNC)
1200 return dvsync_->IsUiDvsyncOn();
1201 #else
1202 return false;
1203 #endif
1204 }
GetUiCommandDelayTime()1205 int64_t VSyncDistributor::GetUiCommandDelayTime()
1206 {
1207 #if defined(RS_ENABLE_DVSYNC)
1208 return dvsync_->GetUiCommandDelayTime();
1209 #else
1210 return 0;
1211 #endif
1212 }
1213
UpdatePendingReferenceTime(int64_t & timeStamp)1214 void VSyncDistributor::UpdatePendingReferenceTime(int64_t &timeStamp)
1215 {
1216 #if defined(RS_ENABLE_DVSYNC)
1217 if (IsDVsyncOn()) {
1218 dvsync_->UpdatePendingReferenceTime(timeStamp);
1219 }
1220 #endif
1221 }
1222
SetHardwareTaskNum(uint32_t num)1223 void VSyncDistributor::SetHardwareTaskNum(uint32_t num)
1224 {
1225 #if defined(RS_ENABLE_DVSYNC)
1226 if (IsDVsyncOn()) {
1227 dvsync_->SetHardwareTaskNum(num);
1228 }
1229 #endif
1230 }
1231 }
1232 }
1233