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 <HwcTrace.h> 17 #include <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 mFpsCounter(0) 33 { 34 CTRACE(); 35 } 36 37 VsyncEventObserver::~VsyncEventObserver() 38 { 39 WARN_IF_NOT_DEINIT(); 40 } 41 42 bool 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 68 void 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 87 bool 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 107 bool 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