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 26namespace android { 27namespace intel { 28 29VsyncManager::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 39VsyncManager::~VsyncManager() 40{ 41 WARN_IF_NOT_DEINIT(); 42} 43 44bool VsyncManager::initialize() 45{ 46 47 mEnabled = false; 48 mVsyncSource = IDisplayDevice::DEVICE_COUNT; 49 mEnableDynamicVsync = !scUsePrimaryVsyncOnly; 50 mInitialized = true; 51 return true; 52} 53 54void 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 66bool 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 92void 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 114int VsyncManager::getVsyncSource() 115{ 116 return mVsyncSource; 117} 118 119void 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 142IDisplayDevice* VsyncManager::getDisplayDevice(int dispType ) { 143 return mHwc.getDisplayDevice(dispType); 144} 145 146int 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 170bool 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 200void 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