18b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol/* 28b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// Copyright (c) 2014 Intel Corporation 38b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// 48b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// Licensed under the Apache License, Version 2.0 (the "License"); 58b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// you may not use this file except in compliance with the License. 68b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// You may obtain a copy of the License at 78b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// 88b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// http://www.apache.org/licenses/LICENSE-2.0 98b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// 108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// Unless required by applicable law or agreed to in writing, software 118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// distributed under the License is distributed on an "AS IS" BASIS, 128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// See the License for the specific language governing permissions and 148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// limitations under the License. 158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol*/ 168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <HwcTrace.h> 178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <SoftVsyncObserver.h> 188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <IDisplayDevice.h> 198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolextern "C" int clock_nanosleep(clockid_t clock_id, int flags, 218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol const struct timespec *request, 228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol struct timespec *remain); 238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 258b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolnamespace android { 268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolnamespace intel { 278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin PujolSoftVsyncObserver::SoftVsyncObserver(IDisplayDevice& disp) 298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol : mDisplayDevice(disp), 308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mDevice(IDisplayDevice::DEVICE_COUNT), 318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mEnabled(false), 328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mRefreshRate(60), // default 60 frames per second 338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mRefreshPeriod(0), 348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mLock(), 358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mCondition(), 368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mNextFakeVSync(0), 378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mExitThread(false), 388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mInitialized(false) 398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{ 408b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} 418b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 428b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin PujolSoftVsyncObserver::~SoftVsyncObserver() 438b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{ 448b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol WARN_IF_NOT_DEINIT(); 458b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} 468b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 478b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool SoftVsyncObserver::initialize() 488b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{ 498b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (mInitialized) { 508b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol WTRACE("object has been initialized"); 518b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return true; 528b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 538b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 548b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mExitThread = false; 558b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mEnabled = false; 568b55c41553ee026c299578b158c4b85de50aaee1Victor Tasayco Loarte mRefreshRate = 60/mDisplayDevice.getFpsDivider(); 578b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mDevice = mDisplayDevice.getType(); 588b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mThread = new VsyncEventPollThread(this); 598b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (!mThread.get()) { 608b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol DEINIT_AND_RETURN_FALSE("failed to create vsync event poll thread."); 618b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 628b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mThread->run("SoftVsyncObserver", PRIORITY_URGENT_DISPLAY); 638b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mInitialized = true; 648b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return true; 658b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} 668b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 678b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid SoftVsyncObserver::deinitialize() 688b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{ 698b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (mEnabled) { 708b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol WTRACE("soft vsync is still enabled"); 718b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol control(false); 728b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 738b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 748b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mExitThread = true; 758b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mCondition.signal(); 768b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 778b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (mThread.get()) { 788b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mThread->requestExitAndWait(); 798b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mThread = NULL; 808b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 818b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mInitialized = false; 828b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} 838b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 848b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid SoftVsyncObserver::setRefreshRate(int rate) 858b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{ 868b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (mEnabled) { 878b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol WTRACE("too late to set refresh rate"); 888b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } else if (rate < 1 || rate > 120) { 898b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol WTRACE("invalid refresh rate %d", rate); 908b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } else { 918b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mRefreshRate = rate; 928b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 938b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} 948b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 958b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool SoftVsyncObserver::control(bool enabled) 968b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{ 978b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (enabled == mEnabled) { 988b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol WTRACE("vsync state %d is not changed", enabled); 998b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return true; 1008b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1018b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1028b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (enabled) { 1038b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mRefreshPeriod = nsecs_t(1e9 / mRefreshRate); 1048b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mNextFakeVSync = systemTime(CLOCK_MONOTONIC) + mRefreshPeriod; 1058b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1068b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mEnabled = enabled; 1078b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mCondition.signal(); 1088b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return true; 1098b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} 1108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool SoftVsyncObserver::threadLoop() 1128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{ 1138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol { // scope for lock 1148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol Mutex::Autolock _l(mLock); 1158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol while (!mEnabled) { 1168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mCondition.wait(mLock); 1178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (mExitThread) { 1188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol ITRACE("exiting thread loop"); 1198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return false; 1208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1258b55c41553ee026c299578b158c4b85de50aaee1Victor Tasayco Loarte const nsecs_t period = mRefreshPeriod * mDisplayDevice.getFpsDivider(); 1268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol const nsecs_t now = systemTime(CLOCK_MONOTONIC); 1278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol nsecs_t next_vsync = mNextFakeVSync; 1288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol nsecs_t sleep = next_vsync - now; 1298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (sleep < 0) { 1308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol // we missed, find where the next vsync should be 1318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol sleep = (period - ((now - next_vsync) % period)); 1328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol next_vsync = now + sleep; 1338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mNextFakeVSync = next_vsync + period; 1358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol struct timespec spec; 1378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol spec.tv_sec = next_vsync / 1000000000; 1388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol spec.tv_nsec = next_vsync % 1000000000; 1398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1408b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol int err; 1418b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol do { 1428b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL); 1438b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } while (err < 0 && errno == EINTR); 1448b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1458b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1468b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol if (err == 0) { 1478b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol mDisplayDevice.onVsync(next_vsync); 1488b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol } 1498b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1508b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol return true; 1518b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} 1528b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 1538b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} // namespace intel 1548b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} // namesapce android 1558b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol 156