| /* |
| // Copyright (c) 2014 Intel Corporation |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| */ |
| |
| #include <HwcTrace.h> |
| #include <IDisplayDevice.h> |
| #include <DisplayQuery.h> |
| #include <BufferManager.h> |
| #include <DisplayPlaneManager.h> |
| #include <Hwcomposer.h> |
| #include <VsyncManager.h> |
| |
| |
| namespace android { |
| namespace intel { |
| |
| VsyncManager::VsyncManager(Hwcomposer &hwc) |
| :mHwc(hwc), |
| mInitialized(false), |
| mEnableDynamicVsync(true), |
| mEnabled(false), |
| mVsyncSource(IDisplayDevice::DEVICE_COUNT), |
| mLock() |
| { |
| } |
| |
| VsyncManager::~VsyncManager() |
| { |
| WARN_IF_NOT_DEINIT(); |
| } |
| |
| bool VsyncManager::initialize() |
| { |
| |
| mEnabled = false; |
| mVsyncSource = IDisplayDevice::DEVICE_COUNT; |
| mEnableDynamicVsync = !scUsePrimaryVsyncOnly; |
| mInitialized = true; |
| return true; |
| } |
| |
| void VsyncManager::deinitialize() |
| { |
| if (mEnabled) { |
| WTRACE("vsync is still enabled"); |
| } |
| |
| mVsyncSource = IDisplayDevice::DEVICE_COUNT; |
| mEnabled = false; |
| mEnableDynamicVsync = !scUsePrimaryVsyncOnly; |
| mInitialized = false; |
| } |
| |
| bool VsyncManager::handleVsyncControl(int disp, bool enabled) |
| { |
| Mutex::Autolock l(mLock); |
| |
| if (disp != IDisplayDevice::DEVICE_PRIMARY) { |
| WTRACE("vsync control on non-primary device %d", disp); |
| return false; |
| } |
| |
| if (mEnabled == enabled) { |
| WTRACE("vsync state %d is not changed", enabled); |
| return true; |
| } |
| |
| if (!enabled) { |
| disableVsync(); |
| mEnabled = false; |
| return true; |
| } else { |
| mEnabled = enableVsync(getCandidate()); |
| return mEnabled; |
| } |
| |
| return false; |
| } |
| |
| void VsyncManager::resetVsyncSource() |
| { |
| Mutex::Autolock l(mLock); |
| |
| if (!mEnableDynamicVsync) { |
| ITRACE("dynamic vsync source switch is not supported"); |
| return; |
| } |
| |
| if (!mEnabled) { |
| return; |
| } |
| |
| int vsyncSource = getCandidate(); |
| if (vsyncSource == mVsyncSource) { |
| return; |
| } |
| |
| disableVsync(); |
| enableVsync(vsyncSource); |
| } |
| |
| int VsyncManager::getVsyncSource() |
| { |
| return mVsyncSource; |
| } |
| |
| void VsyncManager::enableDynamicVsync(bool enable) |
| { |
| Mutex::Autolock l(mLock); |
| if (scUsePrimaryVsyncOnly) { |
| WTRACE("dynamic vsync is not supported"); |
| return; |
| } |
| |
| mEnableDynamicVsync = enable; |
| |
| if (!mEnabled) { |
| return; |
| } |
| |
| int vsyncSource = getCandidate(); |
| if (vsyncSource == mVsyncSource) { |
| return; |
| } |
| |
| disableVsync(); |
| enableVsync(vsyncSource); |
| } |
| |
| IDisplayDevice* VsyncManager::getDisplayDevice(int dispType ) { |
| return mHwc.getDisplayDevice(dispType); |
| } |
| |
| int VsyncManager::getCandidate() |
| { |
| if (!mEnableDynamicVsync) { |
| return IDisplayDevice::DEVICE_PRIMARY; |
| } |
| |
| IDisplayDevice *device = NULL; |
| // use HDMI vsync when connected |
| device = getDisplayDevice(IDisplayDevice::DEVICE_EXTERNAL); |
| if (device && device->isConnected()) { |
| return IDisplayDevice::DEVICE_EXTERNAL; |
| } |
| |
| // use vsync from virtual display when video extended mode is entered |
| if (Hwcomposer::getInstance().getDisplayAnalyzer()->isVideoExtModeActive()) { |
| device = getDisplayDevice(IDisplayDevice::DEVICE_VIRTUAL); |
| if (device && device->isConnected()) { |
| return IDisplayDevice::DEVICE_VIRTUAL; |
| } |
| WTRACE("Could not use vsync from secondary device"); |
| } |
| return IDisplayDevice::DEVICE_PRIMARY; |
| } |
| |
| bool VsyncManager::enableVsync(int candidate) |
| { |
| if (mVsyncSource != IDisplayDevice::DEVICE_COUNT) { |
| WTRACE("vsync has been enabled on %d", mVsyncSource); |
| return true; |
| } |
| |
| IDisplayDevice *device = getDisplayDevice(candidate); |
| if (!device) { |
| ETRACE("invalid vsync source candidate %d", candidate); |
| return false; |
| } |
| |
| if (device->vsyncControl(true)) { |
| mVsyncSource = candidate; |
| return true; |
| } |
| |
| if (candidate != IDisplayDevice::DEVICE_PRIMARY) { |
| WTRACE("failed to enable vsync on display %d, fall back to primary", candidate); |
| device = getDisplayDevice(IDisplayDevice::DEVICE_PRIMARY); |
| if (device && device->vsyncControl(true)) { |
| mVsyncSource = IDisplayDevice::DEVICE_PRIMARY; |
| return true; |
| } |
| } |
| ETRACE("failed to enable vsync on the primary display"); |
| return false; |
| } |
| |
| void VsyncManager::disableVsync() |
| { |
| if (mVsyncSource == IDisplayDevice::DEVICE_COUNT) { |
| WTRACE("vsync has been disabled"); |
| return; |
| } |
| |
| IDisplayDevice *device = getDisplayDevice(mVsyncSource); |
| if (device && !device->vsyncControl(false)) { |
| WTRACE("failed to disable vsync on device %d", mVsyncSource); |
| } |
| mVsyncSource = IDisplayDevice::DEVICE_COUNT; |
| } |
| |
| } // namespace intel |
| } // namespace android |
| |