/* // Copyright (c) 2014 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. */ #include <common/utils/HwcTrace.h> #include <common/observers/VsyncEventObserver.h> #include <PhysicalDevice.h> namespace android { namespace intel { VsyncEventObserver::VsyncEventObserver(PhysicalDevice& disp) : mLock(), mCondition(), mDisplayDevice(disp), mVsyncControl(NULL), mDevice(IDisplayDevice::DEVICE_COUNT), mEnabled(false), mExitThread(false), mInitialized(false) { CTRACE(); } VsyncEventObserver::~VsyncEventObserver() { WARN_IF_NOT_DEINIT(); } bool VsyncEventObserver::initialize() { if (mInitialized) { WLOGTRACE("object has been initialized"); return true; } mExitThread = false; mEnabled = false; mDevice = mDisplayDevice.getType(); mVsyncControl = mDisplayDevice.createVsyncControl(); if (!mVsyncControl || !mVsyncControl->initialize()) { DEINIT_AND_RETURN_FALSE("failed to initialize vsync control"); } mThread = new VsyncEventPollThread(this); if (!mThread.get()) { DEINIT_AND_RETURN_FALSE("failed to create vsync event poll thread."); } mThread->run("VsyncEventObserver", PRIORITY_URGENT_DISPLAY); mInitialized = true; return true; } void VsyncEventObserver::deinitialize() { if (mEnabled) { WLOGTRACE("vsync is still enabled"); control(false); } mInitialized = false; mExitThread = true; mEnabled = false; mCondition.signal(); if (mThread.get()) { mThread->requestExitAndWait(); mThread = NULL; } DEINIT_AND_DELETE_OBJ(mVsyncControl); } bool VsyncEventObserver::control(bool enabled) { ALOGTRACE("enabled = %d on device %d", enabled, mDevice); if (enabled == mEnabled) { WLOGTRACE("vsync state %d is not changed", enabled); return true; } Mutex::Autolock _l(mLock); bool ret = mVsyncControl->control(mDevice, enabled); if (!ret) { ELOGTRACE("failed to control (%d) vsync on display %d", enabled, mDevice); return false; } mEnabled = enabled; mCondition.signal(); return true; } bool VsyncEventObserver::threadLoop() { do { // scope for lock Mutex::Autolock _l(mLock); while (!mEnabled) { mCondition.wait(mLock); if (mExitThread) { ILOGTRACE("exiting thread loop"); return false; } } } while (0); if(mEnabled && mDisplayDevice.isConnected()) { int64_t timestamp; bool ret = mVsyncControl->wait(mDevice, timestamp); if (ret == false) { WLOGTRACE("failed to wait for vsync on display %d, vsync enabled %d", mDevice, mEnabled); usleep(16000); return true; } // notify device mDisplayDevice.onVsync(timestamp); } return true; } } // namespace intel } // namesapce android