1 /* 2 // Copyright(c)2014 IntelCorporation 3 // 4 // LicensedundertheApacheLicense,Version2.0(the"License"); 5 // youmaynotusethisfileexceptincompliancewiththeLicense. 6 // YoumayobtainacopyoftheLicenseat 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unlessrequiredbyapplicablelaworagreedtoinwriting,software 11 // distributedundertheLicenseisdistributedonan"ASIS"BASIS, 12 // WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied. 13 // SeetheLicenseforthespecificlanguagegoverningpermissionsand 14 // limitationsundertheLicense. 15 */ 16 #include <common/utils/HwcTrace.h> 17 #include <common/observers/VsyncEventObserver.h> 18 #include <PhysicalDevice.h> 19 20 namespace android { 21 namespace intel { 22 23 VsyncEventObserver::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 36 VsyncEventObserver::~VsyncEventObserver() 37 { 38 WARN_IF_NOT_DEINIT(); 39 } 40 41 bool 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 67 void 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 86 bool 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 106 bool 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