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 <common/utils/HwcTrace.h> 17#include <common/observers/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{ 33 CTRACE(); 34} 35 36VsyncEventObserver::~VsyncEventObserver() 37{ 38 WARN_IF_NOT_DEINIT(); 39} 40 41bool VsyncEventObserver::initialize() 42{ 43 if (mInitialized) { 44 WLOGTRACE("object has been initialized"); 45 return true; 46 } 47 48 mExitThread = false; 49 mEnabled = false; 50 mDevice = mDisplayDevice.getType(); 51 mVsyncControl = mDisplayDevice.createVsyncControl(); 52 if (!mVsyncControl || !mVsyncControl->initialize()) { 53 DEINIT_AND_RETURN_FALSE("failed to initialize vsync control"); 54 } 55 56 mThread = new VsyncEventPollThread(this); 57 if (!mThread.get()) { 58 DEINIT_AND_RETURN_FALSE("failed to create vsync event poll thread."); 59 } 60 61 mThread->run("VsyncEventObserver", PRIORITY_URGENT_DISPLAY); 62 63 mInitialized = true; 64 return true; 65} 66 67void VsyncEventObserver::deinitialize() 68{ 69 if (mEnabled) { 70 WLOGTRACE("vsync is still enabled"); 71 control(false); 72 } 73 mInitialized = false; 74 mExitThread = true; 75 mEnabled = false; 76 mCondition.signal(); 77 78 if (mThread.get()) { 79 mThread->requestExitAndWait(); 80 mThread = NULL; 81 } 82 83 DEINIT_AND_DELETE_OBJ(mVsyncControl); 84} 85 86bool VsyncEventObserver::control(bool enabled) 87{ 88 ALOGTRACE("enabled = %d on device %d", enabled, mDevice); 89 if (enabled == mEnabled) { 90 WLOGTRACE("vsync state %d is not changed", enabled); 91 return true; 92 } 93 94 Mutex::Autolock _l(mLock); 95 bool ret = mVsyncControl->control(mDevice, enabled); 96 if (!ret) { 97 ELOGTRACE("failed to control (%d) vsync on display %d", enabled, mDevice); 98 return false; 99 } 100 101 mEnabled = enabled; 102 mCondition.signal(); 103 return true; 104} 105 106bool VsyncEventObserver::threadLoop() 107{ 108 do { 109 // scope for lock 110 Mutex::Autolock _l(mLock); 111 while (!mEnabled) { 112 mCondition.wait(mLock); 113 if (mExitThread) { 114 ILOGTRACE("exiting thread loop"); 115 return false; 116 } 117 } 118 } while (0); 119 120 if(mEnabled && mDisplayDevice.isConnected()) { 121 int64_t timestamp; 122 bool ret = mVsyncControl->wait(mDevice, timestamp); 123 if (ret == false) { 124 WLOGTRACE("failed to wait for vsync on display %d, vsync enabled %d", mDevice, mEnabled); 125 usleep(16000); 126 return true; 127 } 128 129 // notify device 130 mDisplayDevice.onVsync(timestamp); 131 } 132 133 return true; 134} 135 136} // namespace intel 137} // namesapce android 138