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