Loading services/surfaceflinger/RefreshRateOverlay.cpp +8 −12 Original line number Diff line number Diff line Loading @@ -200,26 +200,22 @@ void RefreshRateOverlay::primeCache() { } } void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { const auto display = mFlinger.getDefaultDisplayDeviceLocked(); if (!display) { return; } void RefreshRateOverlay::setViewport(ui::Size viewport) { Rect frame(viewport.width >> 3, viewport.height >> 5); frame.offsetBy(viewport.width >> 5, viewport.height >> 4); mLayer->setFrame(frame); const int32_t left = display->getWidth() / 32; const int32_t top = display->getHeight() / 16; const int32_t right = left + display->getWidth() / 8; const int32_t buttom = top + display->getHeight() / 32; mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { auto buffer = mBufferCache[refreshRate.getFps()]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}); mLayer->setFrame(Rect(left, top, right, buttom)); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } }; // namespace android } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wconversion" services/surfaceflinger/RefreshRateOverlay.h +21 −5 Original line number Diff line number Diff line Loading @@ -13,19 +13,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "SurfaceFlinger.h" #include <unordered_map> #include <math/vec4.h> #include <ui/Rect.h> #include <ui/Size.h> #include <utils/StrongPointer.h> #include "Scheduler/RefreshRateConfigs.h" namespace android { class Client; class GraphicBuffer; class IBinder; class IGraphicBufferProducer; class Layer; class SurfaceFlinger; using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; class RefreshRateOverlay { public: RefreshRateOverlay(SurfaceFlinger& flinger); explicit RefreshRateOverlay(SurfaceFlinger&); void changeRefreshRate(const RefreshRate& refreshRate); void setViewport(ui::Size); void changeRefreshRate(const RefreshRate&); private: class SevenSegmentDrawer { Loading Loading @@ -56,7 +72,7 @@ private: void primeCache(); SurfaceFlinger& mFlinger; sp<Client> mClient; const sp<Client> mClient; sp<Layer> mLayer; sp<IBinder> mIBinder; sp<IGraphicBufferProducer> mGbp; Loading @@ -68,4 +84,4 @@ private: const half3 HIGH_FPS_COLOR = half3(0.0f, 1.0f, 0.0f); }; }; // namespace android } // namespace android services/surfaceflinger/SurfaceFlinger.cpp +55 −39 Original line number Diff line number Diff line Loading @@ -582,14 +582,13 @@ void SurfaceFlinger::bootFinished() LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); static_cast<void>(schedule([this]() NO_THREAD_SAFETY_ANALYSIS { static_cast<void>(schedule([this] { readPersistentProperties(); mPowerAdvisor.onBootFinished(); mBootStage = BootStage::FINISHED; if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) { mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this); mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate()); enableRefreshRateOverlay(true); } })); } Loading Loading @@ -934,9 +933,8 @@ int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) { } if (isPrimary) { std::lock_guard<std::mutex> lock(mActiveConfigLock); if (mDesiredActiveConfigChanged) { return mDesiredActiveConfig.configId.value(); if (const auto config = getDesiredActiveConfig()) { return config->configId.value(); } } Loading Loading @@ -1063,14 +1061,7 @@ void SurfaceFlinger::performSetActiveConfig() { ATRACE_CALL(); ALOGV("performSetActiveConfig"); // Store the local variable to release the lock. const auto desiredActiveConfig = [&]() -> std::optional<ActiveConfigInfo> { std::lock_guard<std::mutex> lock(mActiveConfigLock); if (mDesiredActiveConfigChanged) { return mDesiredActiveConfig; } return std::nullopt; }(); const auto desiredActiveConfig = getDesiredActiveConfig(); if (!desiredActiveConfig) { // No desired active config pending to be applied return; Loading Loading @@ -1605,7 +1596,7 @@ void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate, } void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId, hal::Connection connection) { hal::Connection connection) NO_THREAD_SAFETY_ANALYSIS { ALOGV("%s(%d, %" PRIu64 ", %s)", __FUNCTION__, sequenceId, hwcDisplayId, connection == hal::Connection::CONNECTED ? "connected" : "disconnected"); Loading Loading @@ -2679,9 +2670,14 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken, if (currentState.width != drawingState.width || currentState.height != drawingState.height) { display->setDisplaySize(currentState.width, currentState.height); if (display->isPrimary()) { mScheduler->onPrimaryDisplayAreaChanged(currentState.width * currentState.height); } if (mRefreshRateOverlay) { mRefreshRateOverlay->setViewport(display->getSize()); } } } } Loading Loading @@ -5229,16 +5225,16 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r return NO_ERROR; } case 1034: { n = data.readInt32(); if (n == 1 && !mRefreshRateOverlay) { mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this); auto& current = mRefreshRateConfigs->getCurrentRefreshRate(); mRefreshRateOverlay->changeRefreshRate(current); } else if (n == 0) { mRefreshRateOverlay.reset(); } else { switch (n = data.readInt32()) { case 0: case 1: enableRefreshRateOverlay(static_cast<bool>(n)); break; default: { Mutex::Autolock lock(mStateLock); reply->writeBool(mRefreshRateOverlay != nullptr); } } return NO_ERROR; } case 1035: { Loading Loading @@ -5285,29 +5281,26 @@ void SurfaceFlinger::repaintEverythingForHWC() { void SurfaceFlinger::kernelTimerChanged(bool expired) { static bool updateOverlay = property_get_bool("debug.sf.kernel_idle_timer_update_overlay", true); if (!updateOverlay || !mRefreshRateOverlay) return; if (!updateOverlay) return; if (Mutex::Autolock lock(mStateLock); !mRefreshRateOverlay) return; // Update the overlay on the main thread to avoid race conditions with // mRefreshRateConfigs->getCurrentRefreshRate() static_cast<void>(schedule([=]() NO_THREAD_SAFETY_ANALYSIS { if (mRefreshRateOverlay) { const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false); const bool timerExpired = kernelTimerEnabled && expired; const auto& current = [this]() -> const RefreshRate& { std::lock_guard<std::mutex> lock(mActiveConfigLock); if (mDesiredActiveConfigChanged) { return mRefreshRateConfigs->getRefreshRateFromConfigId( mDesiredActiveConfig.configId); } return mRefreshRateConfigs->getCurrentRefreshRate(); }(); static_cast<void>(schedule([=] { const auto desiredActiveConfig = getDesiredActiveConfig(); const auto& current = desiredActiveConfig ? mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig->configId) : mRefreshRateConfigs->getCurrentRefreshRate(); const auto& min = mRefreshRateConfigs->getMinRefreshRate(); if (current != min) { const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false); const bool timerExpired = kernelTimerEnabled && expired; if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) { mRefreshRateOverlay->changeRefreshRate(timerExpired ? min : current); mEventQueue->invalidate(); } mEventQueue->invalidate(); } })); } Loading Loading @@ -6224,6 +6217,29 @@ void SurfaceFlinger::onFrameRateFlexibilityTokenReleased() { })); } void SurfaceFlinger::enableRefreshRateOverlay(bool enable) { static_cast<void>(schedule([=] { std::unique_ptr<RefreshRateOverlay> overlay; if (enable) { overlay = std::make_unique<RefreshRateOverlay>(*this); } { Mutex::Autolock lock(mStateLock); // Destroy the layer of the current overlay, if any, outside the lock. mRefreshRateOverlay.swap(overlay); if (!mRefreshRateOverlay) return; if (const auto display = getDefaultDisplayDeviceLocked()) { mRefreshRateOverlay->setViewport(display->getSize()); } mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate()); } })); } } // namespace android #if defined(__gl_h_) Loading services/surfaceflinger/SurfaceFlinger.h +11 −4 Original line number Diff line number Diff line Loading @@ -829,13 +829,13 @@ private: const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& displaySurface, const sp<IGraphicBufferProducer>& producer); void processDisplayChangesLocked(); void processDisplayChangesLocked() REQUIRES(mStateLock); void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState& state); void processDisplayRemoved(const wp<IBinder>& displayToken); void processDisplayChanged(const wp<IBinder>& displayToken, const DisplayDeviceState& currentState, const DisplayDeviceState& drawingState); void processDisplayHotplugEventsLocked(); const DisplayDeviceState& drawingState) REQUIRES(mStateLock); void processDisplayHotplugEventsLocked() REQUIRES(mStateLock); void dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected); Loading Loading @@ -1216,6 +1216,12 @@ private: * Misc */ std::optional<ActiveConfigInfo> getDesiredActiveConfig() EXCLUDES(mActiveConfigLock) { std::lock_guard<std::mutex> lock(mActiveConfigLock); if (mDesiredActiveConfigChanged) return mDesiredActiveConfig; return std::nullopt; } std::mutex mActiveConfigLock; // This bit is set once we start setting the config. We read from this bit during the // process. If at the end, this bit is different than mDesiredActiveConfig, we restart Loading Loading @@ -1258,7 +1264,8 @@ private: // This should only be accessed on the main thread. nsecs_t mFrameStartTime = 0; std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay; void enableRefreshRateOverlay(bool enable); std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay GUARDED_BY(mStateLock); // Flag used to set override allowed display configs from backdoor bool mDebugDisplayConfigSetByBackdoor = false; Loading Loading
services/surfaceflinger/RefreshRateOverlay.cpp +8 −12 Original line number Diff line number Diff line Loading @@ -200,26 +200,22 @@ void RefreshRateOverlay::primeCache() { } } void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { const auto display = mFlinger.getDefaultDisplayDeviceLocked(); if (!display) { return; } void RefreshRateOverlay::setViewport(ui::Size viewport) { Rect frame(viewport.width >> 3, viewport.height >> 5); frame.offsetBy(viewport.width >> 5, viewport.height >> 4); mLayer->setFrame(frame); const int32_t left = display->getWidth() / 32; const int32_t top = display->getHeight() / 16; const int32_t right = left + display->getWidth() / 8; const int32_t buttom = top + display->getHeight() / 32; mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { auto buffer = mBufferCache[refreshRate.getFps()]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}); mLayer->setFrame(Rect(left, top, right, buttom)); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } }; // namespace android } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wconversion"
services/surfaceflinger/RefreshRateOverlay.h +21 −5 Original line number Diff line number Diff line Loading @@ -13,19 +13,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "SurfaceFlinger.h" #include <unordered_map> #include <math/vec4.h> #include <ui/Rect.h> #include <ui/Size.h> #include <utils/StrongPointer.h> #include "Scheduler/RefreshRateConfigs.h" namespace android { class Client; class GraphicBuffer; class IBinder; class IGraphicBufferProducer; class Layer; class SurfaceFlinger; using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; class RefreshRateOverlay { public: RefreshRateOverlay(SurfaceFlinger& flinger); explicit RefreshRateOverlay(SurfaceFlinger&); void changeRefreshRate(const RefreshRate& refreshRate); void setViewport(ui::Size); void changeRefreshRate(const RefreshRate&); private: class SevenSegmentDrawer { Loading Loading @@ -56,7 +72,7 @@ private: void primeCache(); SurfaceFlinger& mFlinger; sp<Client> mClient; const sp<Client> mClient; sp<Layer> mLayer; sp<IBinder> mIBinder; sp<IGraphicBufferProducer> mGbp; Loading @@ -68,4 +84,4 @@ private: const half3 HIGH_FPS_COLOR = half3(0.0f, 1.0f, 0.0f); }; }; // namespace android } // namespace android
services/surfaceflinger/SurfaceFlinger.cpp +55 −39 Original line number Diff line number Diff line Loading @@ -582,14 +582,13 @@ void SurfaceFlinger::bootFinished() LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); static_cast<void>(schedule([this]() NO_THREAD_SAFETY_ANALYSIS { static_cast<void>(schedule([this] { readPersistentProperties(); mPowerAdvisor.onBootFinished(); mBootStage = BootStage::FINISHED; if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) { mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this); mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate()); enableRefreshRateOverlay(true); } })); } Loading Loading @@ -934,9 +933,8 @@ int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) { } if (isPrimary) { std::lock_guard<std::mutex> lock(mActiveConfigLock); if (mDesiredActiveConfigChanged) { return mDesiredActiveConfig.configId.value(); if (const auto config = getDesiredActiveConfig()) { return config->configId.value(); } } Loading Loading @@ -1063,14 +1061,7 @@ void SurfaceFlinger::performSetActiveConfig() { ATRACE_CALL(); ALOGV("performSetActiveConfig"); // Store the local variable to release the lock. const auto desiredActiveConfig = [&]() -> std::optional<ActiveConfigInfo> { std::lock_guard<std::mutex> lock(mActiveConfigLock); if (mDesiredActiveConfigChanged) { return mDesiredActiveConfig; } return std::nullopt; }(); const auto desiredActiveConfig = getDesiredActiveConfig(); if (!desiredActiveConfig) { // No desired active config pending to be applied return; Loading Loading @@ -1605,7 +1596,7 @@ void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate, } void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId, hal::Connection connection) { hal::Connection connection) NO_THREAD_SAFETY_ANALYSIS { ALOGV("%s(%d, %" PRIu64 ", %s)", __FUNCTION__, sequenceId, hwcDisplayId, connection == hal::Connection::CONNECTED ? "connected" : "disconnected"); Loading Loading @@ -2679,9 +2670,14 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken, if (currentState.width != drawingState.width || currentState.height != drawingState.height) { display->setDisplaySize(currentState.width, currentState.height); if (display->isPrimary()) { mScheduler->onPrimaryDisplayAreaChanged(currentState.width * currentState.height); } if (mRefreshRateOverlay) { mRefreshRateOverlay->setViewport(display->getSize()); } } } } Loading Loading @@ -5229,16 +5225,16 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r return NO_ERROR; } case 1034: { n = data.readInt32(); if (n == 1 && !mRefreshRateOverlay) { mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this); auto& current = mRefreshRateConfigs->getCurrentRefreshRate(); mRefreshRateOverlay->changeRefreshRate(current); } else if (n == 0) { mRefreshRateOverlay.reset(); } else { switch (n = data.readInt32()) { case 0: case 1: enableRefreshRateOverlay(static_cast<bool>(n)); break; default: { Mutex::Autolock lock(mStateLock); reply->writeBool(mRefreshRateOverlay != nullptr); } } return NO_ERROR; } case 1035: { Loading Loading @@ -5285,29 +5281,26 @@ void SurfaceFlinger::repaintEverythingForHWC() { void SurfaceFlinger::kernelTimerChanged(bool expired) { static bool updateOverlay = property_get_bool("debug.sf.kernel_idle_timer_update_overlay", true); if (!updateOverlay || !mRefreshRateOverlay) return; if (!updateOverlay) return; if (Mutex::Autolock lock(mStateLock); !mRefreshRateOverlay) return; // Update the overlay on the main thread to avoid race conditions with // mRefreshRateConfigs->getCurrentRefreshRate() static_cast<void>(schedule([=]() NO_THREAD_SAFETY_ANALYSIS { if (mRefreshRateOverlay) { const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false); const bool timerExpired = kernelTimerEnabled && expired; const auto& current = [this]() -> const RefreshRate& { std::lock_guard<std::mutex> lock(mActiveConfigLock); if (mDesiredActiveConfigChanged) { return mRefreshRateConfigs->getRefreshRateFromConfigId( mDesiredActiveConfig.configId); } return mRefreshRateConfigs->getCurrentRefreshRate(); }(); static_cast<void>(schedule([=] { const auto desiredActiveConfig = getDesiredActiveConfig(); const auto& current = desiredActiveConfig ? mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig->configId) : mRefreshRateConfigs->getCurrentRefreshRate(); const auto& min = mRefreshRateConfigs->getMinRefreshRate(); if (current != min) { const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false); const bool timerExpired = kernelTimerEnabled && expired; if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) { mRefreshRateOverlay->changeRefreshRate(timerExpired ? min : current); mEventQueue->invalidate(); } mEventQueue->invalidate(); } })); } Loading Loading @@ -6224,6 +6217,29 @@ void SurfaceFlinger::onFrameRateFlexibilityTokenReleased() { })); } void SurfaceFlinger::enableRefreshRateOverlay(bool enable) { static_cast<void>(schedule([=] { std::unique_ptr<RefreshRateOverlay> overlay; if (enable) { overlay = std::make_unique<RefreshRateOverlay>(*this); } { Mutex::Autolock lock(mStateLock); // Destroy the layer of the current overlay, if any, outside the lock. mRefreshRateOverlay.swap(overlay); if (!mRefreshRateOverlay) return; if (const auto display = getDefaultDisplayDeviceLocked()) { mRefreshRateOverlay->setViewport(display->getSize()); } mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate()); } })); } } // namespace android #if defined(__gl_h_) Loading
services/surfaceflinger/SurfaceFlinger.h +11 −4 Original line number Diff line number Diff line Loading @@ -829,13 +829,13 @@ private: const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& displaySurface, const sp<IGraphicBufferProducer>& producer); void processDisplayChangesLocked(); void processDisplayChangesLocked() REQUIRES(mStateLock); void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState& state); void processDisplayRemoved(const wp<IBinder>& displayToken); void processDisplayChanged(const wp<IBinder>& displayToken, const DisplayDeviceState& currentState, const DisplayDeviceState& drawingState); void processDisplayHotplugEventsLocked(); const DisplayDeviceState& drawingState) REQUIRES(mStateLock); void processDisplayHotplugEventsLocked() REQUIRES(mStateLock); void dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected); Loading Loading @@ -1216,6 +1216,12 @@ private: * Misc */ std::optional<ActiveConfigInfo> getDesiredActiveConfig() EXCLUDES(mActiveConfigLock) { std::lock_guard<std::mutex> lock(mActiveConfigLock); if (mDesiredActiveConfigChanged) return mDesiredActiveConfig; return std::nullopt; } std::mutex mActiveConfigLock; // This bit is set once we start setting the config. We read from this bit during the // process. If at the end, this bit is different than mDesiredActiveConfig, we restart Loading Loading @@ -1258,7 +1264,8 @@ private: // This should only be accessed on the main thread. nsecs_t mFrameStartTime = 0; std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay; void enableRefreshRateOverlay(bool enable); std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay GUARDED_BY(mStateLock); // Flag used to set override allowed display configs from backdoor bool mDebugDisplayConfigSetByBackdoor = false; Loading