SF: Track missed frames and optionally drop them
Adds code to track whether SurfaceFlinger has sent two frames to HWC in the same vsync window. This can occur if one frame is delayed so far it slips into the next window or just if one frame takes an abnormal amount of time. If this occurs, it shows up as FrameMissed in systrace. Also adds a property debug.sf.drop_missed_frames which, if set, tells SurfaceFlinger to skip sending a frame to HWC (i.e., calling prepare/set) when we detect this condition, which can help prevent backpressure from the HWC implementation. Bug: 22513558 Change-Id: I2df0d44cec5fd6edba419388d8c90b5710d1a5b6
This commit is contained in:
parent
177a416625
commit
14cd37cf3d
@ -163,6 +163,9 @@ SurfaceFlinger::SurfaceFlinger()
|
|||||||
property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
|
property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
|
||||||
mGpuToCpuSupported = !atoi(value);
|
mGpuToCpuSupported = !atoi(value);
|
||||||
|
|
||||||
|
property_get("debug.sf.drop_missed_frames", value, "0");
|
||||||
|
mDropMissedFrames = atoi(value);
|
||||||
|
|
||||||
property_get("debug.sf.showupdates", value, "0");
|
property_get("debug.sf.showupdates", value, "0");
|
||||||
mDebugRegion = atoi(value);
|
mDebugRegion = atoi(value);
|
||||||
|
|
||||||
@ -919,12 +922,31 @@ bool SurfaceFlinger::handleMessageInvalidate() {
|
|||||||
|
|
||||||
void SurfaceFlinger::handleMessageRefresh() {
|
void SurfaceFlinger::handleMessageRefresh() {
|
||||||
ATRACE_CALL();
|
ATRACE_CALL();
|
||||||
preComposition();
|
|
||||||
rebuildLayerStacks();
|
static nsecs_t previousExpectedPresent = 0;
|
||||||
setUpHWComposer();
|
nsecs_t expectedPresent = mPrimaryDispSync.computeNextRefresh(0);
|
||||||
doDebugFlashRegions();
|
static bool previousFrameMissed = false;
|
||||||
doComposition();
|
bool frameMissed = (expectedPresent == previousExpectedPresent);
|
||||||
postComposition();
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
previousExpectedPresent = mPrimaryDispSync.computeNextRefresh(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceFlinger::doDebugFlashRegions()
|
void SurfaceFlinger::doDebugFlashRegions()
|
||||||
|
@ -445,6 +445,7 @@ private:
|
|||||||
RenderEngine* mRenderEngine;
|
RenderEngine* mRenderEngine;
|
||||||
nsecs_t mBootTime;
|
nsecs_t mBootTime;
|
||||||
bool mGpuToCpuSupported;
|
bool mGpuToCpuSupported;
|
||||||
|
bool mDropMissedFrames;
|
||||||
sp<EventThread> mEventThread;
|
sp<EventThread> mEventThread;
|
||||||
sp<EventThread> mSFEventThread;
|
sp<EventThread> mSFEventThread;
|
||||||
sp<EventControlThread> mEventControlThread;
|
sp<EventControlThread> mEventControlThread;
|
||||||
|
Loading…
Reference in New Issue
Block a user