SurfaceFlinger: Some fixes to DispSync
Pass negative offsets to DispSync to fix the scheduling
when SurfaceFlinger uses negative offsets.
Change-Id: I1f9544b064305c87f973120cc1bc59a0268b78e5
Bug: 132284303
Test: UI-Bench
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 95ff9d0..e59d459 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -92,7 +92,6 @@
mPeriod = period;
if (!mModelLocked && referenceTimeChanged) {
for (auto& eventListener : mEventListeners) {
- eventListener.mHasFired = false;
eventListener.mLastEventTime =
mReferenceTime - mPeriod + mPhase + eventListener.mPhase;
}
@@ -123,13 +122,6 @@
void unlockModel() {
Mutex::Autolock lock(mMutex);
- if (mModelLocked) {
- for (auto& eventListener : mEventListeners) {
- if (eventListener.mLastEventTime > mReferenceTime) {
- eventListener.mHasFired = true;
- }
- }
- }
mModelLocked = false;
ATRACE_INT("DispSync:ModelLocked", mModelLocked);
}
@@ -259,10 +251,6 @@
listener.mLastCallbackTime = lastCallbackTime;
}
- if (!mModelLocked && listener.mLastEventTime > mReferenceTime) {
- listener.mHasFired = true;
- }
-
mEventListeners.push_back(listener);
mCond.signal();
@@ -305,7 +293,14 @@
} else if (diff < -mPeriod / 2) {
diff += mPeriod;
}
+
+ if (phase < 0 && oldPhase > 0) {
+ diff += mPeriod;
+ } else if (phase > 0 && oldPhase < 0) {
+ diff -= mPeriod;
+ }
eventListener.mLastEventTime -= diff;
+ eventListener.mLastCallbackTime -= diff;
mCond.signal();
return NO_ERROR;
}
@@ -320,7 +315,6 @@
nsecs_t mLastEventTime;
nsecs_t mLastCallbackTime;
DispSync::Callback* mCallback;
- bool mHasFired = false;
};
struct CallbackInvocation {
@@ -368,12 +362,7 @@
eventListener.mName);
continue;
}
- if (eventListener.mHasFired && !mModelLocked) {
- eventListener.mLastEventTime = t;
- ALOGV("[%s] [%s] Skipping event due to already firing", mName,
- eventListener.mName);
- continue;
- }
+
CallbackInvocation ci;
ci.mCallback = eventListener.mCallback;
ci.mEventTime = t;
@@ -382,7 +371,6 @@
callbackInvocations.push_back(ci);
eventListener.mLastEventTime = t;
eventListener.mLastCallbackTime = now;
- eventListener.mHasFired = true;
}
}
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
index 00948ae..265b8aa 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
@@ -27,14 +27,16 @@
namespace android {
-DispSyncSource::DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
+DispSyncSource::DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset,
+ nsecs_t offsetThresholdForNextVsync, bool traceVsync,
const char* name)
: mName(name),
mTraceVsync(traceVsync),
mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
mVsyncEventLabel(base::StringPrintf("VSYNC-%s", name)),
mDispSync(dispSync),
- mPhaseOffset(phaseOffset) {}
+ mPhaseOffset(phaseOffset),
+ mOffsetThresholdForNextVsync(offsetThresholdForNextVsync) {}
void DispSyncSource::setVSyncEnabled(bool enable) {
std::lock_guard lock(mVsyncMutex);
@@ -64,15 +66,15 @@
void DispSyncSource::setPhaseOffset(nsecs_t phaseOffset) {
std::lock_guard lock(mVsyncMutex);
-
- // Normalize phaseOffset to [0, period)
- auto period = mDispSync->getPeriod();
- phaseOffset %= period;
- if (phaseOffset < 0) {
- // If we're here, then phaseOffset is in (-period, 0). After this
- // operation, it will be in (0, period)
- phaseOffset += period;
+ const nsecs_t period = mDispSync->getPeriod();
+ // Check if offset should be handled as negative
+ if (phaseOffset >= mOffsetThresholdForNextVsync) {
+ phaseOffset -= period;
}
+
+ // Normalize phaseOffset to [-period, period)
+ const int numPeriods = phaseOffset / period;
+ phaseOffset -= numPeriods * period;
mPhaseOffset = phaseOffset;
// If we're not enabled, we don't need to mess with the listeners
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.h b/services/surfaceflinger/Scheduler/DispSyncSource.h
index 4759699..b6785c5 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.h
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.h
@@ -25,7 +25,8 @@
class DispSyncSource final : public VSyncSource, private DispSync::Callback {
public:
- DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync, const char* name);
+ DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, nsecs_t offsetThresholdForNextVsync,
+ bool traceVsync, const char* name);
~DispSyncSource() override = default;
@@ -53,6 +54,7 @@
std::mutex mVsyncMutex;
nsecs_t mPhaseOffset GUARDED_BY(mVsyncMutex);
+ const nsecs_t mOffsetThresholdForNextVsync;
bool mEnabled GUARDED_BY(mVsyncMutex) = false;
};
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index e2a348e..ef53933 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -119,14 +119,15 @@
}
sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
- const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
+ const char* connectionName, nsecs_t phaseOffsetNs, nsecs_t offsetThresholdForNextVsync,
+ ResyncCallback resyncCallback,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
const int64_t id = sNextId++;
ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
std::unique_ptr<EventThread> eventThread =
makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
- std::move(interceptCallback));
+ offsetThresholdForNextVsync, std::move(interceptCallback));
auto eventThreadConnection =
createConnectionInternal(eventThread.get(), std::move(resyncCallback));
@@ -138,10 +139,12 @@
}
std::unique_ptr<EventThread> Scheduler::makeEventThread(
- const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+ const char* connectionName, DispSync* dispSync, nsecs_t phaseOffsetNs,
+ nsecs_t offsetThresholdForNextVsync,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
std::unique_ptr<VSyncSource> eventThreadSource =
- std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, connectionName);
+ std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, offsetThresholdForNextVsync,
+ true, connectionName);
return std::make_unique<impl::EventThread>(std::move(eventThreadSource),
std::move(interceptCallback), connectionName);
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index d311f62..226cb18 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -96,8 +96,8 @@
virtual ~Scheduler();
/** Creates an EventThread connection. */
- sp<ConnectionHandle> createConnection(const char* connectionName, int64_t phaseOffsetNs,
- ResyncCallback,
+ sp<ConnectionHandle> createConnection(const char* connectionName, nsecs_t phaseOffsetNs,
+ nsecs_t offsetThresholdForNextVsync, ResyncCallback,
impl::EventThread::InterceptVSyncsCallback);
sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle,
@@ -184,7 +184,8 @@
protected:
virtual std::unique_ptr<EventThread> makeEventThread(
- const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+ const char* connectionName, DispSync* dispSync, nsecs_t phaseOffsetNs,
+ nsecs_t offsetThresholdForNextVsync,
impl::EventThread::InterceptVSyncsCallback interceptCallback);
private:
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index 41c3a3a..73a1fb9 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -56,10 +56,12 @@
// appEarly: Like sfEarly, but for the app-vsync
// appEarlyGl: Like sfEarlyGl, but for the app-vsync.
// appLate: The regular app vsync phase offset.
- void setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late) {
+ void setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late,
+ nsecs_t thresholdForNextVsync) {
mEarlyOffsets = early;
mEarlyGlOffsets = earlyGl;
mLateOffsets = late;
+ mThresholdForNextVsync = thresholdForNextVsync;
if (mSfConnectionHandle && late.sf != mOffsets.load().sf) {
mScheduler->setPhaseOffset(mSfConnectionHandle, late.sf);
@@ -192,6 +194,7 @@
Offsets mLateOffsets;
Offsets mEarlyOffsets;
Offsets mEarlyGlOffsets;
+ nsecs_t mThresholdForNextVsync;
EventThread* mSfEventThread = nullptr;
EventThread* mAppEventThread = nullptr;