• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Android Open Source Project
2 //
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 expresso or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "VsyncThread.h"
15 
16 #include "aemu/base/system/System.h"
17 
18 namespace gfxstream {
19 
VsyncThread(uint64_t vsyncPeriodNs)20 VsyncThread::VsyncThread(uint64_t vsyncPeriodNs) :
21     mPeriodNs(vsyncPeriodNs),
22     mThread([this] { threadFunc(); }) {
23     mThread.start();
24 }
25 
~VsyncThread()26 VsyncThread::~VsyncThread() {
27     exit();
28 }
29 
schedule(VsyncTask task)30 void VsyncThread::schedule(VsyncTask task) {
31     mChannel.send({ CommandType::Default, task });
32 }
33 
setPeriod(uint64_t newPeriod)34 void VsyncThread::setPeriod(uint64_t newPeriod) {
35     mChannel.send({ CommandType::ChangePeriod, {}, newPeriod });
36 }
37 
exit()38 void VsyncThread::exit() {
39     mChannel.send({ CommandType::Exit });
40     mThread.wait();
41 }
42 
threadFunc()43 void VsyncThread::threadFunc() {
44     VsyncThreadCommand currentCommand;
45     uint64_t lastTimeUs = ~0ULL;
46     uint64_t phasedWaitTimeUs;
47     uint64_t currentUs;
48 
49     while (true) {
50         uint64_t periodUs = mPeriodNs / 1000ULL;
51         currentUs = android::base::getHighResTimeUs();
52 
53         if (lastTimeUs == ~0ULL) {
54             phasedWaitTimeUs = currentUs + periodUs;
55         } else {
56             phasedWaitTimeUs =
57                 periodUs * ((currentUs - lastTimeUs) / periodUs + 1) +
58                 lastTimeUs;
59         }
60 
61         android::base::sleepToUs(phasedWaitTimeUs);
62 
63         lastTimeUs = phasedWaitTimeUs;
64 
65         while (mChannel.tryReceive(&currentCommand)) {
66             switch (currentCommand.type) {
67                 case CommandType::Exit:
68                     return;
69                 case CommandType::ChangePeriod:
70                     mPeriodNs = currentCommand.newPeriod;
71                     break;
72                 case CommandType::Default:
73                 default:
74                     currentCommand.task(mCount);
75             }
76         }
77 
78         ++mCount;
79     }
80 }
81 
82 }  // namespace gfxstream