SF: Remove DisplayDevice::onVsync
The DisplayDevice does not exist until the display transaction created
by the `configure` stage is committed. HWComposer::DisplayData already
stores the present timestamp, so query that and remove DisplayDevice's
duplicate.
Bug: 248345991
Bug: 241285876
Test: Hotplug
Change-Id: I6b0cbe2e36d2d4ec0e2a1a1197b60e0c9ae60bfe
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index d7704a8..9102139 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -70,6 +70,7 @@
MOCK_METHOD1(disconnectDisplay, void(HalDisplayId));
MOCK_CONST_METHOD1(hasDeviceComposition, bool(const std::optional<DisplayId>&));
MOCK_CONST_METHOD1(getPresentFence, sp<Fence>(HalDisplayId));
+ MOCK_METHOD(nsecs_t, getPresentTimestamp, (PhysicalDisplayId), (const, override));
MOCK_CONST_METHOD2(getLayerReleaseFence, sp<Fence>(HalDisplayId, HWC2::Layer*));
MOCK_METHOD3(setOutputBuffer,
status_t(HalVirtualDisplayId, const sp<Fence>&, const sp<GraphicBuffer>&));
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index a25296c..f8115eb 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -238,16 +238,6 @@
return refreshRateConfigs().getActiveModePtr()->getVsyncPeriod();
}
-nsecs_t DisplayDevice::getRefreshTimestamp() const {
- const nsecs_t now = systemTime(CLOCK_MONOTONIC);
- const auto vsyncPeriodNanos = getVsyncPeriodFromHWC();
- return now - ((now - mLastHwVsync) % vsyncPeriodNanos);
-}
-
-void DisplayDevice::onVsync(nsecs_t timestamp) {
- mLastHwVsync = timestamp;
-}
-
ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
return mCompositionDisplay->getState().dataspace;
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 0f52aff..510df81 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -233,9 +233,7 @@
bool onKernelTimerChanged(std::optional<DisplayModeId>, bool timerExpired);
void animateRefreshRateOverlay();
- void onVsync(nsecs_t timestamp);
nsecs_t getVsyncPeriodFromHWC() const;
- nsecs_t getRefreshTimestamp() const;
status_t setRefreshRatePolicy(
const std::optional<scheduler::RefreshRateConfigs::Policy>& policy,
@@ -273,8 +271,6 @@
std::optional<float> mStagedBrightness;
float mBrightness = -1.f;
- std::atomic<nsecs_t> mLastHwVsync = 0;
-
// TODO(b/182939859): Remove special cases for primary display.
const bool mIsPrimary;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 486eaf8..96399e2 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -70,7 +70,7 @@
struct ComposerCallback {
virtual void onComposerHalHotplug(hal::HWDisplayId, hal::Connection) = 0;
virtual void onComposerHalRefresh(hal::HWDisplayId) = 0;
- virtual void onComposerHalVsync(hal::HWDisplayId, int64_t timestamp,
+ virtual void onComposerHalVsync(hal::HWDisplayId, nsecs_t timestamp,
std::optional<hal::VsyncPeriodNanos>) = 0;
virtual void onComposerHalVsyncPeriodTimingChanged(hal::HWDisplayId,
const hal::VsyncPeriodChangeTimeline&) = 0;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 15d5041..0a4ad97 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -144,7 +144,7 @@
return mUpdateDeviceProductInfoOnHotplugReconnect;
}
-bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) {
+bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, nsecs_t timestamp) {
const auto displayId = toPhysicalDisplayId(hwcDisplayId);
if (!displayId) {
LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
@@ -160,13 +160,13 @@
// with the same timestamp when turning the display off and on. This
// is a bug in the HWC implementation, but filter the extra events
// out here so they don't cause havoc downstream.
- if (timestamp == displayData.lastHwVsync) {
+ if (timestamp == displayData.lastPresentTimestamp) {
ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")",
to_string(*displayId).c_str(), timestamp);
return false;
}
- displayData.lastHwVsync = timestamp;
+ displayData.lastPresentTimestamp = timestamp;
}
const auto tag = "HW_VSYNC_" + to_string(*displayId);
@@ -485,6 +485,11 @@
return mDisplayData.at(displayId).lastPresentFence;
}
+nsecs_t HWComposer::getPresentTimestamp(PhysicalDisplayId displayId) const {
+ RETURN_IF_INVALID_DISPLAY(displayId, 0);
+ return mDisplayData.at(displayId).lastPresentTimestamp;
+}
+
sp<Fence> HWComposer::getLayerReleaseFence(HalDisplayId displayId, HWC2::Layer* layer) const {
RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
const auto& displayFences = mDisplayData.at(displayId).releaseFences;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 92a8f30..6c43d8b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -160,8 +160,9 @@
// reset state when a display is disconnected
virtual void disconnectDisplay(HalDisplayId) = 0;
- // get the present fence received from the last call to present.
+ // Get the present fence/timestamp received from the last call to present.
virtual sp<Fence> getPresentFence(HalDisplayId) const = 0;
+ virtual nsecs_t getPresentTimestamp(PhysicalDisplayId) const = 0;
// Get last release fence for the given layer
virtual sp<Fence> getLayerReleaseFence(HalDisplayId, HWC2::Layer*) const = 0;
@@ -214,7 +215,7 @@
// TODO(b/157555476): Remove when the framework has proper support for headless mode
virtual bool updatesDeviceProductInfoOnHotplugReconnect() const = 0;
- virtual bool onVsync(hal::HWDisplayId, int64_t timestamp) = 0;
+ virtual bool onVsync(hal::HWDisplayId, nsecs_t timestamp) = 0;
virtual void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) = 0;
virtual bool isConnected(PhysicalDisplayId) const = 0;
@@ -343,8 +344,9 @@
// reset state when a display is disconnected
void disconnectDisplay(HalDisplayId) override;
- // get the present fence received from the last call to present.
+ // Get the present fence/timestamp received from the last call to present.
sp<Fence> getPresentFence(HalDisplayId) const override;
+ nsecs_t getPresentTimestamp(PhysicalDisplayId) const override;
// Get last release fence for the given layer
sp<Fence> getLayerReleaseFence(HalDisplayId, HWC2::Layer*) const override;
@@ -387,7 +389,7 @@
bool updatesDeviceProductInfoOnHotplugReconnect() const override;
- bool onVsync(hal::HWDisplayId, int64_t timestamp) override;
+ bool onVsync(hal::HWDisplayId, nsecs_t timestamp) override;
void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) override;
bool isConnected(PhysicalDisplayId) const override;
@@ -456,7 +458,10 @@
struct DisplayData {
std::unique_ptr<HWC2::Display> hwcDisplay;
+
sp<Fence> lastPresentFence = Fence::NO_FENCE; // signals when the last set op retires
+ nsecs_t lastPresentTimestamp = 0;
+
std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
bool validateWasSkipped;
@@ -466,8 +471,6 @@
std::mutex vsyncEnabledLock;
hal::Vsync vsyncEnabled GUARDED_BY(vsyncEnabledLock) = hal::Vsync::DISABLE;
-
- nsecs_t lastHwVsync = 0;
};
std::optional<DisplayIdentificationInfo> onHotplugConnect(hal::HWDisplayId);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 13437a4..96ee28c 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -3918,9 +3918,14 @@
mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
} else if (const auto displayId = PhysicalDisplayId::tryCast(display->getId());
displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
- // The HWC doesn't support present fences, so use the refresh
- // timestamp instead.
- const nsecs_t actualPresentTime = display->getRefreshTimestamp();
+ // The HWC doesn't support present fences, so use the present timestamp instead.
+ const nsecs_t presentTimestamp =
+ mFlinger->getHwComposer().getPresentTimestamp(*displayId);
+
+ const nsecs_t now = systemTime(CLOCK_MONOTONIC);
+ const nsecs_t vsyncPeriod = display->getVsyncPeriodFromHWC();
+ const nsecs_t actualPresentTime = now - ((now - presentTimestamp) % vsyncPeriod);
+
mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime,
refreshRate, renderRate, vote, gameMode);
mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(),
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index f3551ae..4024e1f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1893,17 +1893,12 @@
ATRACE_FORMAT("onComposerHalVsync%s", tracePeriod.c_str());
Mutex::Autolock lock(mStateLock);
- const auto displayId = getHwComposer().toPhysicalDisplayId(hwcDisplayId);
- if (displayId) {
- const auto token = getPhysicalDisplayTokenLocked(*displayId);
- const auto display = getDisplayDeviceLocked(token);
- display->onVsync(timestamp);
- }
if (!getHwComposer().onVsync(hwcDisplayId, timestamp)) {
return;
}
+ const auto displayId = getHwComposer().toPhysicalDisplayId(hwcDisplayId);
const bool isActiveDisplay =
displayId && getPhysicalDisplayTokenLocked(*displayId) == mActiveDisplayToken;
if (!isActiveDisplay) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index fdaacf0..00b0c1e 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -608,7 +608,7 @@
void binderDied(const wp<IBinder>& who) override;
// HWC2::ComposerCallback overrides:
- void onComposerHalVsync(hal::HWDisplayId, int64_t timestamp,
+ void onComposerHalVsync(hal::HWDisplayId, nsecs_t timestamp,
std::optional<hal::VsyncPeriodNanos>) override;
void onComposerHalHotplug(hal::HWDisplayId, hal::Connection) override;
void onComposerHalRefresh(hal::HWDisplayId) override;