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)20VsyncThread::VsyncThread(uint64_t vsyncPeriodNs) : 21 mPeriodNs(vsyncPeriodNs), 22 mThread([this] { threadFunc(); }) { 23 mThread.start(); 24 } 25 ~VsyncThread()26VsyncThread::~VsyncThread() { 27 exit(); 28 } 29 schedule(VsyncTask task)30void VsyncThread::schedule(VsyncTask task) { 31 mChannel.send({ CommandType::Default, task }); 32 } 33 setPeriod(uint64_t newPeriod)34void VsyncThread::setPeriod(uint64_t newPeriod) { 35 mChannel.send({ CommandType::ChangePeriod, {}, newPeriod }); 36 } 37 exit()38void VsyncThread::exit() { 39 mChannel.send({ CommandType::Exit }); 40 mThread.wait(); 41 } 42 threadFunc()43void 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(¤tCommand)) { 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