summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Dan Stoza <stoza@google.com> 2016-07-01 13:33:38 -0700
committer Dan Stoza <stoza@google.com> 2016-07-06 09:52:51 -0700
commit05dacfb68af895fce3cc8ebb0b4aa06c6c336e26 (patch)
tree76d979531ac6ed78cdac7065d4fb70752cbcf0c3
parent1ce6581ac788eaad58fd3329c2154af7dd74aa3d (diff)
HWC2: Backpressure missed vsyncs into apps
Adds a mechanism to detect whether the prior frame SurfaceFlinger presented to hardware composer was actually picked up or not. We then use this mechanism to avoid pushing two frames in the same vsync. This backpressure is passed back to applications by not latching any buffers, which will manifest as dequeueBuffer stalling until SurfaceFlinger releases a buffer on the following vsync. Also makes the former INVALIDATE_ON_VSYNC behavior the only behavior so that this functionality works correctly. Bug: 29413700 Change-Id: Ibde358e45423ee6fea7b5e09ff65e49c4ad67baa
-rw-r--r--services/surfaceflinger/MessageQueue.cpp23
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp45
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h3
-rw-r--r--services/surfaceflinger/SurfaceFlinger_hwc1.cpp32
4 files changed, 26 insertions, 77 deletions
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index 34dc24b1f3..974c7a340e 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -134,31 +134,12 @@ status_t MessageQueue::postMessage(
}
-/* when INVALIDATE_ON_VSYNC is set SF only processes
- * buffer updates on VSYNC and performs a refresh immediately
- * after.
- *
- * when INVALIDATE_ON_VSYNC is set to false, SF will instead
- * perform the buffer updates immediately, but the refresh only
- * at the next VSYNC.
- * THIS MODE IS BUGGY ON GALAXY NEXUS AND WILL CAUSE HANGS
- */
-#define INVALIDATE_ON_VSYNC 1
-
void MessageQueue::invalidate() {
-#if INVALIDATE_ON_VSYNC
mEvents->requestNextVsync();
-#else
- mHandler->dispatchInvalidate();
-#endif
}
void MessageQueue::refresh() {
-#if INVALIDATE_ON_VSYNC
mHandler->dispatchRefresh();
-#else
- mEvents->requestNextVsync();
-#endif
}
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
@@ -172,11 +153,7 @@ int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
for (int i=0 ; i<n ; i++) {
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
-#if INVALIDATE_ON_VSYNC
mHandler->dispatchInvalidate();
-#else
- mHandler->dispatchRefresh();
-#endif
break;
}
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9a2747da75..c541668a82 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -167,9 +167,6 @@ SurfaceFlinger::SurfaceFlinger()
property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
mGpuToCpuSupported = !atoi(value);
- property_get("debug.sf.drop_missed_frames", value, "0");
- mDropMissedFrames = atoi(value);
-
property_get("debug.sf.showupdates", value, "0");
mDebugRegion = atoi(value);
@@ -933,6 +930,14 @@ bool SurfaceFlinger::handleMessageTransaction() {
bool SurfaceFlinger::handleMessageInvalidate() {
ATRACE_CALL();
+ bool frameMissed = !mHadClientComposition &&
+ mPreviousPresentFence != Fence::NO_FENCE &&
+ mPreviousPresentFence->getSignalTime() == INT64_MAX;
+ ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
+ if (frameMissed) {
+ signalLayerUpdate();
+ return false;
+ }
return handlePageFlip();
}
@@ -940,36 +945,22 @@ void SurfaceFlinger::handleMessageRefresh() {
ATRACE_CALL();
nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
- static nsecs_t previousExpectedPresent = 0;
- nsecs_t expectedPresent = mPrimaryDispSync.computeNextRefresh(0);
- static bool previousFrameMissed = false;
- bool frameMissed = (expectedPresent == previousExpectedPresent);
- if (frameMissed != previousFrameMissed) {
- ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
- }
- previousFrameMissed = frameMissed;
-
- if (CC_UNLIKELY(mDropMissedFrames && frameMissed)) {
- // Latch buffers, but don't send anything to HWC, then signal another
- // wakeup for the next vsync
- preComposition();
- repaintEverything();
- } else {
- preComposition();
- rebuildLayerStacks();
- setUpHWComposer();
- doDebugFlashRegions();
- doComposition();
- postComposition(refreshStartTime);
- }
+
+ preComposition();
+ rebuildLayerStacks();
+ setUpHWComposer();
+ doDebugFlashRegions();
+ doComposition();
+ postComposition(refreshStartTime);
+
+ mPreviousPresentFence = mHwc->getRetireFence(HWC_DISPLAY_PRIMARY);
+ mHadClientComposition = mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY);
// Release any buffers which were replaced this frame
for (auto& layer : mLayersWithQueuedFrames) {
layer->releasePendingBuffer();
}
mLayersWithQueuedFrames.clear();
-
- previousExpectedPresent = mPrimaryDispSync.computeNextRefresh(0);
}
void SurfaceFlinger::doDebugFlashRegions()
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 28666e2aa5..0df39a45f0 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -468,7 +468,6 @@ private:
RenderEngine* mRenderEngine;
nsecs_t mBootTime;
bool mGpuToCpuSupported;
- bool mDropMissedFrames;
sp<EventThread> mEventThread;
sp<EventThread> mSFEventThread;
sp<EventControlThread> mEventControlThread;
@@ -488,6 +487,8 @@ private:
bool mAnimCompositionPending;
#ifdef USE_HWC2
std::vector<sp<Layer>> mLayersWithQueuedFrames;
+ sp<Fence> mPreviousPresentFence = Fence::NO_FENCE;
+ bool mHadClientComposition = false;
#endif
// this may only be written from the main thread with mStateLock held
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 83f7b08f27..d84d4e1b7f 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -166,9 +166,6 @@ SurfaceFlinger::SurfaceFlinger()
property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
mGpuToCpuSupported = !atoi(value);
- property_get("debug.sf.drop_missed_frames", value, "0");
- mDropMissedFrames = atoi(value);
-
property_get("debug.sf.showupdates", value, "0");
mDebugRegion = atoi(value);
@@ -944,30 +941,13 @@ void SurfaceFlinger::handleMessageRefresh() {
ATRACE_CALL();
nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
- static nsecs_t previousExpectedPresent = 0;
- nsecs_t expectedPresent = mPrimaryDispSync.computeNextRefresh(0);
- static bool previousFrameMissed = false;
- bool frameMissed = (expectedPresent == previousExpectedPresent);
- if (frameMissed != previousFrameMissed) {
- ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
- }
- previousFrameMissed = frameMissed;
-
- if (CC_UNLIKELY(mDropMissedFrames && frameMissed)) {
- // Latch buffers, but don't send anything to HWC, then signal another
- // wakeup for the next vsync
- preComposition();
- repaintEverything();
- } else {
- preComposition();
- rebuildLayerStacks();
- setUpHWComposer();
- doDebugFlashRegions();
- doComposition();
- postComposition(refreshStartTime);
- }
- previousExpectedPresent = mPrimaryDispSync.computeNextRefresh(0);
+ preComposition();
+ rebuildLayerStacks();
+ setUpHWComposer();
+ doDebugFlashRegions();
+ doComposition();
+ postComposition(refreshStartTime);
}
void SurfaceFlinger::doDebugFlashRegions()