From 14cd37cf3d7d783eaeb4cfb5f1f9e712d3b49578 Mon Sep 17 00:00:00 2001 From: Dan Stoza Date: Thu, 9 Jul 2015 12:43:33 -0700 Subject: 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 --- services/surfaceflinger/SurfaceFlinger.cpp | 34 ++++++++++++++++++++++++------ services/surfaceflinger/SurfaceFlinger.h | 1 + 2 files changed, 29 insertions(+), 6 deletions(-) (limited to 'services/surfaceflinger') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9b9867d..01ffac2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -163,6 +163,9 @@ 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); @@ -919,12 +922,31 @@ bool SurfaceFlinger::handleMessageInvalidate() { void SurfaceFlinger::handleMessageRefresh() { ATRACE_CALL(); - preComposition(); - rebuildLayerStacks(); - setUpHWComposer(); - doDebugFlashRegions(); - doComposition(); - postComposition(); + + 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(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() diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 3759a92..b3baadd 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -445,6 +445,7 @@ private: RenderEngine* mRenderEngine; nsecs_t mBootTime; bool mGpuToCpuSupported; + bool mDropMissedFrames; sp mEventThread; sp mSFEventThread; sp mEventControlThread; -- cgit v1.1 From f2699fc3a8c12b2bf95120c068801e050168bd96 Mon Sep 17 00:00:00 2001 From: Dan Stoza Date: Mon, 31 Aug 2015 12:06:48 -0700 Subject: SF: Add colorTransform to DisplayInfo Adds the colorTransform field, which defines a vendor-specific color transform (e.g., wide gamut, sRGB, etc.) to the DisplayInfo class, and populates it from the HWC interface. Bug: 20853317 Change-Id: I153edc36a361407656f3eb5082b96c2da2ecbec7 --- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 27 +++++++++++++++++++--- .../surfaceflinger/DisplayHardware/HWComposer.h | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 1 + 3 files changed, 26 insertions(+), 3 deletions(-) (limited to 'services/surfaceflinger') diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 2dad005..0859149 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -336,10 +336,20 @@ static const uint32_t DISPLAY_ATTRIBUTES[] = { HWC_DISPLAY_HEIGHT, HWC_DISPLAY_DPI_X, HWC_DISPLAY_DPI_Y, + HWC_DISPLAY_COLOR_TRANSFORM, HWC_DISPLAY_NO_ATTRIBUTE, }; #define NUM_DISPLAY_ATTRIBUTES (sizeof(DISPLAY_ATTRIBUTES) / sizeof(DISPLAY_ATTRIBUTES)[0]) +static const uint32_t PRE_HWC15_DISPLAY_ATTRIBUTES[] = { + HWC_DISPLAY_VSYNC_PERIOD, + HWC_DISPLAY_WIDTH, + HWC_DISPLAY_HEIGHT, + HWC_DISPLAY_DPI_X, + HWC_DISPLAY_DPI_Y, + HWC_DISPLAY_NO_ATTRIBUTE, +}; + status_t HWComposer::queryDisplayProperties(int disp) { LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)); @@ -362,6 +372,12 @@ status_t HWComposer::queryDisplayProperties(int disp) { for (size_t c = 0; c < numConfigs; ++c) { err = mHwc->getDisplayAttributes(mHwc, disp, configs[c], DISPLAY_ATTRIBUTES, values); + // If this is a pre-1.5 HWC, it may not know about color transform, so + // try again with a smaller set of attributes + if (err != NO_ERROR) { + err = mHwc->getDisplayAttributes(mHwc, disp, configs[c], + PRE_HWC15_DISPLAY_ATTRIBUTES, values); + } if (err != NO_ERROR) { // we can't get this display's info. turn it off. mDisplayData[disp].connected = false; @@ -386,6 +402,9 @@ status_t HWComposer::queryDisplayProperties(int disp) { case HWC_DISPLAY_DPI_Y: config.ydpi = values[i] / 1000.0f; break; + case HWC_DISPLAY_COLOR_TRANSFORM: + config.colorTransform = values[i]; + break; default: ALOG_ASSERT(false, "unknown display attribute[%zu] %#x", i, DISPLAY_ATTRIBUTES[i]); @@ -1162,9 +1181,11 @@ void HWComposer::dump(String8& result) const { result.appendFormat(" Display[%zd] configurations (* current):\n", i); for (size_t c = 0; c < disp.configs.size(); ++c) { const DisplayConfig& config(disp.configs[c]); - result.appendFormat(" %s%zd: %ux%u, xdpi=%f, ydpi=%f, refresh=%" PRId64 "\n", - c == disp.currentConfig ? "* " : "", c, config.width, config.height, - config.xdpi, config.ydpi, config.refresh); + result.appendFormat(" %s%zd: %ux%u, xdpi=%f, ydpi=%f" + ", refresh=%" PRId64 ", colorTransform=%d\n", + c == disp.currentConfig ? "* " : "", c, + config.width, config.height, config.xdpi, config.ydpi, + config.refresh, config.colorTransform); } if (disp.list) { diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index cc98b4c..5e0b3d8 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -257,6 +257,7 @@ public: float xdpi; float ydpi; nsecs_t refresh; + int colorTransform; }; // Query display parameters. Pass in a display index (e.g. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 01ffac2..fdc3650 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -632,6 +632,7 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& display, info.ydpi = ydpi; info.fps = float(1e9 / hwConfig.refresh); info.appVsyncOffset = VSYNC_EVENT_PHASE_OFFSET_NS; + info.colorTransform = hwConfig.colorTransform; // This is how far in advance a buffer must be queued for // presentation at a given time. If you want a buffer to appear -- cgit v1.1