diff options
| author | 2019-01-12 05:36:09 +0000 | |
|---|---|---|
| committer | 2019-01-12 05:36:09 +0000 | |
| commit | e3dbb294940461cad6a04625501b93d3daf6fb0f (patch) | |
| tree | 304e83611657a54a81449dfe656987c9431292dd /services/surfaceflinger/SurfaceFlinger.cpp | |
| parent | 65047e1ab2899cd2b349345a248a4550202e92a3 (diff) | |
| parent | 7d1d68309356cd676100fdd4915aaffac1f36180 (diff) | |
Merge "SF: Adding callback to Scheduler for setting refresh rate to 60 and 90."
Diffstat (limited to 'services/surfaceflinger/SurfaceFlinger.cpp')
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 114 |
1 files changed, 89 insertions, 25 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index dc82b3267f..bd16d645f1 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -729,6 +729,11 @@ void SurfaceFlinger::init() { ALOGE("Run StartPropertySetThread failed!"); } + if (mUseScheduler) { + mScheduler->setExpiredIdleTimerCallback([this]() { setRefreshRateTo(60.f /* fps */); }); + mScheduler->setResetIdleTimerCallback([this]() { setRefreshRateTo(90.f /* fps */); }); + } + ALOGV("Done initializing"); } @@ -934,14 +939,45 @@ int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) { return display->getActiveConfig(); } -void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& display, int mode) { +status_t SurfaceFlinger::setActiveConfigAsync(const sp<IBinder>& displayToken, int mode) { + ATRACE_NAME("setActiveConfigAsync"); + postMessageAsync(new LambdaMessage([=] { setActiveConfigInternal(displayToken, mode); })); + return NO_ERROR; +} + +status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) { + ATRACE_NAME("setActiveConfigSync"); + postMessageSync(new LambdaMessage([&] { setActiveConfigInternal(displayToken, mode); })); + return NO_ERROR; +} + +void SurfaceFlinger::setActiveConfigInternal(const sp<IBinder>& displayToken, int mode) { + Vector<DisplayInfo> configs; + getDisplayConfigs(displayToken, &configs); + if (mode < 0 || mode >= static_cast<int>(configs.size())) { + ALOGE("Attempt to set active config %d for display with %zu configs", mode, configs.size()); + return; + } + + const auto display = getDisplayDevice(displayToken); + if (!display) { + ALOGE("Attempt to set active config %d for invalid display token %p", mode, + displayToken.get()); + return; + } if (display->isVirtual()) { - ALOGE("%s: Invalid operation on virtual display", __FUNCTION__); + ALOGW("Attempt to set active config %d for virtual display", mode); + return; + } + int currentDisplayPowerMode = display->getPowerMode(); + if (currentDisplayPowerMode != HWC_POWER_MODE_NORMAL) { + // Don't change active config when in AoD. return; } int currentMode = display->getActiveConfig(); if (mode == currentMode) { + // Don't update config if we are already running in the desired mode. return; } @@ -950,29 +986,9 @@ void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& display, i display->setActiveConfig(mode); getHwComposer().setActiveConfig(*displayId, mode); -} -status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) { - postMessageSync(new LambdaMessage([&] { - Vector<DisplayInfo> configs; - getDisplayConfigs(displayToken, &configs); - if (mode < 0 || mode >= static_cast<int>(configs.size())) { - ALOGE("Attempt to set active config %d for display with %zu configs", mode, - configs.size()); - return; - } - const auto display = getDisplayDevice(displayToken); - if (!display) { - ALOGE("Attempt to set active config %d for invalid display token %p", mode, - displayToken.get()); - } else if (display->isVirtual()) { - ALOGW("Attempt to set active config %d for virtual display", mode); - } else { - setActiveConfigInternal(display, mode); - } - })); - - return NO_ERROR; + ATRACE_INT("ActiveConfigMode", mode); + resyncToHardwareVsync(true); } status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& displayToken, @@ -1382,6 +1398,49 @@ void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) { *compositorTiming = getBE().mCompositorTiming; } +void SurfaceFlinger::setRefreshRateTo(float newFps) { + const auto displayId = getInternalDisplayId(); + if (!displayId || mBootStage != BootStage::FINISHED) { + return; + } + // TODO(b/113612090): There should be a message queue flush here. Because this esentially + // runs on a mainthread, we cannot call postMessageSync. This can be resolved in a better + // manner, once the setActiveConfig is synchronous, and is executed at a known time in a + // refresh cycle. + + // Don't do any updating if the current fps is the same as the new one. + const auto activeConfig = getHwComposer().getActiveConfig(*displayId); + const nsecs_t currentVsyncPeriod = activeConfig->getVsyncPeriod(); + if (currentVsyncPeriod == 0) { + return; + } + // TODO(b/113612090): Consider having an enum value for correct refresh rates, rather than + // floating numbers. + const float currentFps = 1e9 / currentVsyncPeriod; + if (std::abs(currentFps - newFps) <= 1) { + return; + } + + auto configs = getHwComposer().getConfigs(*displayId); + for (int i = 0; i < configs.size(); i++) { + const nsecs_t vsyncPeriod = configs.at(i)->getVsyncPeriod(); + if (vsyncPeriod == 0) { + continue; + } + const float fps = 1e9 / vsyncPeriod; + // TODO(b/113612090): There should be a better way at determining which config + // has the right refresh rate. + if (std::abs(fps - newFps) <= 1) { + const auto display = getBuiltInDisplay(HWC_DISPLAY_PRIMARY); + if (!display) return; + // This is posted in async function to avoid deadlock when getDisplayDevice + // requires mStateLock. + setActiveConfigAsync(display, i); + ATRACE_INT("FPS", newFps); + } + } +} + void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, HWC2::Connection connection) { ALOGV("%s(%d, %" PRIu64 ", %s)", __FUNCTION__, sequenceId, hwcDisplayId, @@ -1413,7 +1472,7 @@ void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*hwcDispl if (sequenceId != getBE().mComposerSequenceId) { return; } - repaintEverything(); + repaintEverythingForHWC(); } void SurfaceFlinger::setVsyncEnabled(EventThread::DisplayType /*displayType*/, bool enabled) { @@ -5177,6 +5236,11 @@ void SurfaceFlinger::repaintEverything() { signalTransaction(); } +void SurfaceFlinger::repaintEverythingForHWC() { + mRepaintEverything = true; + mEventQueue->invalidateForHWC(); +} + // A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope class WindowDisconnector { public: |