1/* 2// Copyright (c) 2014 Intel Corporation 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15*/ 16#include <HwcTrace.h> 17#include <VsyncEventObserver.h> 18#include <PhysicalDevice.h> 19 20namespace android { 21namespace intel { 22 23VsyncEventObserver::VsyncEventObserver(PhysicalDevice& disp) 24 : mLock(), 25 mCondition(), 26 mDisplayDevice(disp), 27 mVsyncControl(NULL), 28 mDevice(IDisplayDevice::DEVICE_COUNT), 29 mEnabled(false), 30 mExitThread(false), 31 mInitialized(false), 32 mFpsCounter(0) 33{ 34 CTRACE(); 35} 36 37VsyncEventObserver::~VsyncEventObserver() 38{ 39 WARN_IF_NOT_DEINIT(); 40} 41 42bool VsyncEventObserver::initialize() 43{ 44 if (mInitialized) { 45 WTRACE("object has been initialized"); 46 return true; 47 } 48 49 mExitThread = false; 50 mEnabled = false; 51 mDevice = mDisplayDevice.getType(); 52 mVsyncControl = mDisplayDevice.createVsyncControl(); 53 if (!mVsyncControl || !mVsyncControl->initialize()) { 54 DEINIT_AND_RETURN_FALSE("failed to initialize vsync control"); 55 } 56 57 mThread = new VsyncEventPollThread(this); 58 if (!mThread.get()) { 59 DEINIT_AND_RETURN_FALSE("failed to create vsync event poll thread."); 60 } 61 62 mThread->run("VsyncEventObserver", PRIORITY_URGENT_DISPLAY); 63 64 mInitialized = true; 65 return true; 66} 67 68void VsyncEventObserver::deinitialize() 69{ 70 if (mEnabled) { 71 WTRACE("vsync is still enabled"); 72 control(false); 73 } 74 mInitialized = false; 75 mExitThread = true; 76 mEnabled = false; 77 mCondition.signal(); 78 79 if (mThread.get()) { 80 mThread->requestExitAndWait(); 81 mThread = NULL; 82 } 83 84 DEINIT_AND_DELETE_OBJ(mVsyncControl); 85} 86 87bool VsyncEventObserver::control(bool enabled) 88{ 89 ATRACE("enabled = %d on device %d", enabled, mDevice); 90 if (enabled == mEnabled) { 91 WTRACE("vsync state %d is not changed", enabled); 92 return true; 93 } 94 95 Mutex::Autolock _l(mLock); 96 bool ret = mVsyncControl->control(mDevice, enabled); 97 if (!ret) { 98 ETRACE("failed to control (%d) vsync on display %d", enabled, mDevice); 99 return false; 100 } 101 102 mEnabled = enabled; 103 mCondition.signal(); 104 return true; 105} 106 107bool VsyncEventObserver::threadLoop() 108{ 109 do { 110 // scope for lock 111 Mutex::Autolock _l(mLock); 112 while (!mEnabled) { 113 mCondition.wait(mLock); 114 if (mExitThread) { 115 ITRACE("exiting thread loop"); 116 return false; 117 } 118 } 119 } while (0); 120 121 if(mEnabled && mDisplayDevice.isConnected()) { 122 int64_t timestamp; 123 bool ret = mVsyncControl->wait(mDevice, timestamp); 124 if (ret == false) { 125 WTRACE("failed to wait for vsync on display %d, vsync enabled %d", mDevice, mEnabled); 126 usleep(16000); 127 return true; 128 } 129 130 // send vsync event notification every hwc.fps_divider 131 if ((mFpsCounter++) % mDisplayDevice.getFpsDivider() == 0) 132 mDisplayDevice.onVsync(timestamp); 133 } 134 135 return true; 136} 137 138} // namespace intel 139} // namesapce android 140