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 // use vsync from virtual display when video extended mode is entered
160 if (Hwcomposer::getInstance().getDisplayAnalyzer()->isVideoExtModeActive()) {
161 device = getDisplayDevice(IDisplayDevice::DEVICE_VIRTUAL);
162 if (device && device->isConnected()) {
163 return IDisplayDevice::DEVICE_VIRTUAL;
164 }
165 WTRACE("Could not use vsync from secondary device");
166 }
167 return IDisplayDevice::DEVICE_PRIMARY;
168 }
169
enableVsync(int candidate)170 bool VsyncManager::enableVsync(int candidate)
171 {
172 if (mVsyncSource != IDisplayDevice::DEVICE_COUNT) {
173 WTRACE("vsync has been enabled on %d", mVsyncSource);
174 return true;
175 }
176
177 IDisplayDevice *device = getDisplayDevice(candidate);
178 if (!device) {
179 ETRACE("invalid vsync source candidate %d", candidate);
180 return false;
181 }
182
183 if (device->vsyncControl(true)) {
184 mVsyncSource = candidate;
185 return true;
186 }
187
188 if (candidate != IDisplayDevice::DEVICE_PRIMARY) {
189 WTRACE("failed to enable vsync on display %d, fall back to primary", candidate);
190 device = getDisplayDevice(IDisplayDevice::DEVICE_PRIMARY);
191 if (device && device->vsyncControl(true)) {
192 mVsyncSource = IDisplayDevice::DEVICE_PRIMARY;
193 return true;
194 }
195 }
196 ETRACE("failed to enable vsync on the primary display");
197 return false;
198 }
199
disableVsync()200 void VsyncManager::disableVsync()
201 {
202 if (mVsyncSource == IDisplayDevice::DEVICE_COUNT) {
203 WTRACE("vsync has been disabled");
204 return;
205 }
206
207 IDisplayDevice *device = getDisplayDevice(mVsyncSource);
208 if (device && !device->vsyncControl(false)) {
209 WTRACE("failed to disable vsync on device %d", mVsyncSource);
210 }
211 mVsyncSource = IDisplayDevice::DEVICE_COUNT;
212 }
213
214 } // namespace intel
215 } // namespace android
216
217