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
20 namespace android {
21 namespace intel {
22
VsyncEventObserver(PhysicalDevice & disp)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
~VsyncEventObserver()36 VsyncEventObserver::~VsyncEventObserver()
37 {
38 WARN_IF_NOT_DEINIT();
39 }
40
initialize()41 bool VsyncEventObserver::initialize()
42 {
43 if (mInitialized) {
44 WTRACE("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
deinitialize()67 void VsyncEventObserver::deinitialize()
68 {
69 if (mEnabled) {
70 WTRACE("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
control(bool enabled)86 bool VsyncEventObserver::control(bool enabled)
87 {
88 ATRACE("enabled = %d on device %d", enabled, mDevice);
89 if (enabled == mEnabled) {
90 WTRACE("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 ETRACE("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
threadLoop()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 ITRACE("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 WTRACE("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