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
17 #include <HwcTrace.h>
18 #include <IDisplayDevice.h>
19 #include <DisplayQuery.h>
20 #include <BufferManager.h>
21 #include <DisplayPlaneManager.h>
22 #include <Hwcomposer.h>
23 #include <VsyncManager.h>
24
25
26 namespace android {
27 namespace intel {
28
VsyncManager(Hwcomposer & hwc)29 VsyncManager::VsyncManager(Hwcomposer &hwc)
30 :mHwc(hwc),
31 mInitialized(false),
32 mEnableDynamicVsync(true),
33 mEnabled(false),
34 mVsyncSource(IDisplayDevice::DEVICE_COUNT),
35 mLock()
36 {
37 }
38
~VsyncManager()39 VsyncManager::~VsyncManager()
40 {
41 WARN_IF_NOT_DEINIT();
42 }
43
initialize()44 bool VsyncManager::initialize()
45 {
46
47 mEnabled = false;
48 mVsyncSource = IDisplayDevice::DEVICE_COUNT;
49 mEnableDynamicVsync = !scUsePrimaryVsyncOnly;
50 mInitialized = true;
51 return true;
52 }
53
deinitialize()54 void VsyncManager::deinitialize()
55 {
56 if (mEnabled) {
57 WTRACE("vsync is still enabled");
58 }
59
60 mVsyncSource = IDisplayDevice::DEVICE_COUNT;
61 mEnabled = false;
62 mEnableDynamicVsync = !scUsePrimaryVsyncOnly;
63 mInitialized = false;
64 }
65
handleVsyncControl(int disp,bool enabled)66 bool VsyncManager::handleVsyncControl(int disp, bool enabled)
67 {
68 Mutex::Autolock l(mLock);
69
70 if (disp != IDisplayDevice::DEVICE_PRIMARY) {
71 WTRACE("vsync control on non-primary device %d", disp);
72 return false;
73 }
74
75 if (mEnabled == enabled) {
76 WTRACE("vsync state %d is not changed", enabled);
77 return true;
78 }
79
80 if (!enabled) {
81 disableVsync();
82 mEnabled = false;
83 return true;
84 } else {
85 mEnabled = enableVsync(getCandidate());
86 return mEnabled;
87 }
88
89 return false;
90 }
91
resetVsyncSource()92 void VsyncManager::resetVsyncSource()
93 {
94 Mutex::Autolock l(mLock);
95
96 if (!mEnableDynamicVsync) {
97 ITRACE("dynamic vsync source switch is not supported");
98 return;
99 }
100
101 if (!mEnabled) {
102 return;
103 }
104
105 int vsyncSource = getCandidate();
106 if (vsyncSource == mVsyncSource) {
107 return;
108 }
109
110 disableVsync();
111 enableVsync(vsyncSource);
112 }
113
getVsyncSource()114 int VsyncManager::getVsyncSource()
115 {
116 return mVsyncSource;
117 }
118
enableDynamicVsync(bool enable)119 void VsyncManager::enableDynamicVsync(bool enable)
120 {
121 Mutex::Autolock l(mLock);
122 if (scUsePrimaryVsyncOnly) {
123 WTRACE("dynamic vsync is not supported");
124 return;
125 }
126
127 mEnableDynamicVsync = enable;
128
129 if (!mEnabled) {
130 return;
131 }
132
133 int vsyncSource = getCandidate();
134 if (vsyncSource == mVsyncSource) {
135 return;
136 }
137
138 disableVsync();
139 enableVsync(vsyncSource);
140 }
141
getDisplayDevice(int dispType)142 IDisplayDevice* VsyncManager::getDisplayDevice(int dispType ) {
143 return mHwc.getDisplayDevice(dispType);
144 }
145
getCandidate()146 int VsyncManager::getCandidate()
147 {
148 if (!mEnableDynamicVsync) {
149 return IDisplayDevice::DEVICE_PRIMARY;
150 }
151
152 IDisplayDevice *device = NULL;
153 // use HDMI vsync when connected
154 device = getDisplayDevice(IDisplayDevice::DEVICE_EXTERNAL);
155 if (device && device->isConnected()) {
156 return IDisplayDevice::DEVICE_EXTERNAL;
157 }
158
159 #ifdef INTEL_WIDI_MERRIFIELD
160 // use vsync from virtual display when video extended mode is entered
161 if (Hwcomposer::getInstance().getDisplayAnalyzer()->isVideoExtModeActive()) {
162 device = getDisplayDevice(IDisplayDevice::DEVICE_VIRTUAL);
163 if (device && device->isConnected()) {
164 return IDisplayDevice::DEVICE_VIRTUAL;
165 }
166 WTRACE("Could not use vsync from secondary device");
167 }
168 #endif
169 return IDisplayDevice::DEVICE_PRIMARY;
170 }
171
enableVsync(int candidate)172 bool VsyncManager::enableVsync(int candidate)
173 {
174 if (mVsyncSource != IDisplayDevice::DEVICE_COUNT) {
175 WTRACE("vsync has been enabled on %d", mVsyncSource);
176 return true;
177 }
178
179 IDisplayDevice *device = getDisplayDevice(candidate);
180 if (!device) {
181 ETRACE("invalid vsync source candidate %d", candidate);
182 return false;
183 }
184
185 if (device->vsyncControl(true)) {
186 mVsyncSource = candidate;
187 return true;
188 }
189
190 if (candidate != IDisplayDevice::DEVICE_PRIMARY) {
191 WTRACE("failed to enable vsync on display %d, fall back to primary", candidate);
192 device = getDisplayDevice(IDisplayDevice::DEVICE_PRIMARY);
193 if (device && device->vsyncControl(true)) {
194 mVsyncSource = IDisplayDevice::DEVICE_PRIMARY;
195 return true;
196 }
197 }
198 ETRACE("failed to enable vsync on the primary display");
199 return false;
200 }
201
disableVsync()202 void VsyncManager::disableVsync()
203 {
204 if (mVsyncSource == IDisplayDevice::DEVICE_COUNT) {
205 WTRACE("vsync has been disabled");
206 return;
207 }
208
209 IDisplayDevice *device = getDisplayDevice(mVsyncSource);
210 if (device && !device->vsyncControl(false)) {
211 WTRACE("failed to disable vsync on device %d", mVsyncSource);
212 }
213 mVsyncSource = IDisplayDevice::DEVICE_COUNT;
214 }
215
216 } // namespace intel
217 } // namespace android
218
219