summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJorim Jaggi <jjaggi@google.com>2018-06-19 15:57:08 +0200
committerJorim Jaggi <jjaggi@google.com>2018-06-21 12:47:46 +0000
commite203e04eeb438a58202bf632c617ef293af3093a (patch)
tree2f31de13657a9dd5d908c6aba589035185b23ed3
parentba88c2e9bcfb8665ef8fe55eab3b3d0895d0592c (diff)
downloadnative-e203e04eeb438a58202bf632c617ef293af3093a.tar.gz
Allow for more flexible vsync-offsets
The issue with just one single sf early offset is that this may be too early in case of steady rendering, i.e. when a Wide-Color-Gamut window is on screen. Instead, we allow for separate offsets in case we are in GL comp but the transaction wasn't marked as early, and when the transaction is marked as early. In addition to that, we also allow the app-vsync to be adjusted in these scenarios. Bug: 110112323 Change-Id: I26d73b88b4e9e609ceedb604e8338452d9a89093 Merged-In: I26d73b88b4e9e609ceedb604e8338452d9a89093
-rw-r--r--services/surfaceflinger/DispSync.cpp8
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp46
-rw-r--r--services/surfaceflinger/VSyncModulator.h107
3 files changed, 109 insertions, 52 deletions
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index 7acbd11bc5..37dc27d80d 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -222,7 +222,13 @@ public:
// Pretend that the last time this event was handled at the same frame but with the
// new offset to allow for a seamless offset change without double-firing or
// skipping.
- listener.mLastEventTime -= (oldPhase - phase);
+ nsecs_t diff = oldPhase - phase;
+ if (diff > mPeriod / 2) {
+ diff -= mPeriod;
+ } else if (diff < -mPeriod / 2) {
+ diff += mPeriod;
+ }
+ listener.mLastEventTime -= diff;
mCond.signal();
return NO_ERROR;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 87baf8c8a8..66b41f5c76 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -331,11 +331,26 @@ SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) {
auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
- property_get("debug.sf.early_phase_offset_ns", value, "0");
- const int earlyWakeupOffsetOffsetNs = atoi(value);
- ALOGI_IF(earlyWakeupOffsetOffsetNs != 0, "Enabling separate early offset");
- mVsyncModulator.setPhaseOffsets(sfVsyncPhaseOffsetNs - earlyWakeupOffsetOffsetNs,
- sfVsyncPhaseOffsetNs);
+ property_get("debug.sf.early_phase_offset_ns", value, "-1");
+ const int earlySfOffsetNs = atoi(value);
+
+ property_get("debug.sf.early_gl_phase_offset_ns", value, "-1");
+ const int earlyGlSfOffsetNs = atoi(value);
+
+ property_get("debug.sf.early_app_phase_offset_ns", value, "-1");
+ const int earlyAppOffsetNs = atoi(value);
+
+ property_get("debug.sf.early_gl_app_phase_offset_ns", value, "-1");
+ const int earlyGlAppOffsetNs = atoi(value);
+
+ const VSyncModulator::Offsets earlyOffsets =
+ {earlySfOffsetNs != -1 ? earlySfOffsetNs : sfVsyncPhaseOffsetNs,
+ earlyAppOffsetNs != -1 ? earlyAppOffsetNs : vsyncPhaseOffsetNs};
+ const VSyncModulator::Offsets earlyGlOffsets =
+ {earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs : sfVsyncPhaseOffsetNs,
+ earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs : vsyncPhaseOffsetNs};
+ mVsyncModulator.setPhaseOffsets(earlyOffsets, earlyGlOffsets,
+ {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs});
// We should be reading 'persist.sys.sf.color_saturation' here
// but since /data may be encrypted, we need to wait until after vold
@@ -662,7 +677,7 @@ void SurfaceFlinger::init() {
},
"sfEventThread");
mEventQueue->setEventThread(mSFEventThread.get());
- mVsyncModulator.setEventThread(mSFEventThread.get());
+ mVsyncModulator.setEventThreads(mSFEventThread.get(), mEventThread.get());
// Get a RenderEngine for the given display / config (can't fail)
getBE().mRenderEngine =
@@ -4207,9 +4222,22 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
colorizer.bold(result);
result.append("DispSync configuration: ");
colorizer.reset(result);
- result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, early sf phase %" PRId64
- " ns, present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
- vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, mVsyncModulator.getEarlyPhaseOffset(),
+ const auto [sfEarlyOffset, appEarlyOffset] = mVsyncModulator.getEarlyOffsets();
+ const auto [sfEarlyGlOffset, appEarlyGlOffset] = mVsyncModulator.getEarlyGlOffsets();
+ result.appendFormat(
+ "app phase %" PRId64 " ns, "
+ "sf phase %" PRId64 " ns, "
+ "early app phase %" PRId64 " ns, "
+ "early sf phase %" PRId64 " ns, "
+ "early app gl phase %" PRId64 " ns, "
+ "early sf gl phase %" PRId64 " ns, "
+ "present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
+ vsyncPhaseOffsetNs,
+ sfVsyncPhaseOffsetNs,
+ appEarlyOffset,
+ sfEarlyOffset,
+ appEarlyGlOffset,
+ sfEarlyOffset,
dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod());
result.append("\n");
diff --git a/services/surfaceflinger/VSyncModulator.h b/services/surfaceflinger/VSyncModulator.h
index d526313994..e071a599c9 100644
--- a/services/surfaceflinger/VSyncModulator.h
+++ b/services/surfaceflinger/VSyncModulator.h
@@ -36,6 +36,11 @@ private:
public:
+ struct Offsets {
+ nsecs_t sf;
+ nsecs_t app;
+ };
+
enum TransactionStart {
EARLY,
NORMAL
@@ -43,21 +48,32 @@ public:
// Sets the phase offsets
//
- // early: the phase offset when waking up early. May be the same as late, in which case we don't
- // shift offsets.
- // late: the regular sf phase offset.
- void setPhaseOffsets(nsecs_t early, nsecs_t late) {
- mEarlyPhaseOffset = early;
- mLatePhaseOffset = late;
- mPhaseOffset = late;
+ // sfEarly: The phase offset when waking up SF early, which happens when marking a transaction
+ // as early. May be the same as late, in which case we don't shift offsets.
+ // sfEarlyGl: Like sfEarly, but only if we used GL composition. If we use both GL composition
+ // and the transaction was marked as early, we'll use sfEarly.
+ // sfLate: The regular SF vsync phase offset.
+ // 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) {
+ mEarlyOffsets = early;
+ mEarlyGlOffsets = earlyGl;
+ mLateOffsets = late;
+ mOffsets = late;
+ }
+
+ Offsets getEarlyOffsets() const {
+ return mEarlyOffsets;
}
- nsecs_t getEarlyPhaseOffset() const {
- return mEarlyPhaseOffset;
+ Offsets getEarlyGlOffsets() const {
+ return mEarlyGlOffsets;
}
- void setEventThread(EventThread* eventThread) {
- mEventThread = eventThread;
+ void setEventThreads(EventThread* sfEventThread, EventThread* appEventThread) {
+ mSfEventThread = sfEventThread;
+ mAppEventThread = appEventThread;
}
void setTransactionStart(TransactionStart transactionStart) {
@@ -71,63 +87,70 @@ public:
return;
}
mTransactionStart = transactionStart;
- updatePhaseOffsets();
+ updateOffsets();
}
void onTransactionHandled() {
if (mTransactionStart == TransactionStart::NORMAL) return;
mTransactionStart = TransactionStart::NORMAL;
- updatePhaseOffsets();
+ updateOffsets();
}
void onRefreshed(bool usedRenderEngine) {
- bool updatePhaseOffsetsNeeded = false;
+ bool updateOffsetsNeeded = false;
if (mRemainingEarlyFrameCount > 0) {
mRemainingEarlyFrameCount--;
- updatePhaseOffsetsNeeded = true;
+ updateOffsetsNeeded = true;
}
if (usedRenderEngine != mLastFrameUsedRenderEngine) {
mLastFrameUsedRenderEngine = usedRenderEngine;
- updatePhaseOffsetsNeeded = true;
+ updateOffsetsNeeded = true;
}
- if (updatePhaseOffsetsNeeded) {
- updatePhaseOffsets();
+ if (updateOffsetsNeeded) {
+ updateOffsets();
}
}
private:
- void updatePhaseOffsets() {
+ void updateOffsets() {
+ const Offsets desired = getOffsets();
+ const Offsets current = mOffsets;
+
+ bool changed = false;
+ if (desired.sf != current.sf) {
+ mSfEventThread->setPhaseOffset(desired.sf);
+ changed = true;
+ }
+ if (desired.app != current.app) {
+ mAppEventThread->setPhaseOffset(desired.app);
+ changed = true;
+ }
- // Do not change phase offsets if disabled.
- if (mEarlyPhaseOffset == mLatePhaseOffset) return;
+ if (changed) {
+ mOffsets = desired;
+ }
+ }
- if (shouldUseEarlyOffset()) {
- if (mPhaseOffset != mEarlyPhaseOffset) {
- if (mEventThread) {
- mEventThread->setPhaseOffset(mEarlyPhaseOffset);
- }
- mPhaseOffset = mEarlyPhaseOffset;
- }
+ Offsets getOffsets() {
+ if (mTransactionStart == TransactionStart::EARLY || mRemainingEarlyFrameCount > 0) {
+ return mEarlyOffsets;
+ } else if (mLastFrameUsedRenderEngine) {
+ return mEarlyGlOffsets;
} else {
- if (mPhaseOffset != mLatePhaseOffset) {
- if (mEventThread) {
- mEventThread->setPhaseOffset(mLatePhaseOffset);
- }
- mPhaseOffset = mLatePhaseOffset;
- }
+ return mLateOffsets;
}
}
- bool shouldUseEarlyOffset() {
- return mTransactionStart == TransactionStart::EARLY || mLastFrameUsedRenderEngine
- || mRemainingEarlyFrameCount > 0;
- }
+ Offsets mLateOffsets;
+ Offsets mEarlyOffsets;
+ Offsets mEarlyGlOffsets;
+
+ EventThread* mSfEventThread = nullptr;
+ EventThread* mAppEventThread = nullptr;
+
+ std::atomic<Offsets> mOffsets;
- nsecs_t mLatePhaseOffset = 0;
- nsecs_t mEarlyPhaseOffset = 0;
- EventThread* mEventThread = nullptr;
- std::atomic<nsecs_t> mPhaseOffset = 0;
std::atomic<TransactionStart> mTransactionStart = TransactionStart::NORMAL;
std::atomic<bool> mLastFrameUsedRenderEngine = false;
std::atomic<int> mRemainingEarlyFrameCount = 0;