From b7a0549c983bef103ce07eb3af5905febc6e538e Mon Sep 17 00:00:00 2001 From: Jesse Hall Date: Thu, 14 Aug 2014 15:45:06 -0700 Subject: [PATCH] surfaceflinger: skip composition for empty frames By not committing the results of composition for empty frames, we avoid spitting out series of black frames for virtual displays that don't have visible layers. We still draw one black frame when going from having layers to not having any. In particular, this avoids having a series of empty frames due to re-compositing the primary display in the period between creating the virtual display and adding layers to it. Bug: 16786752 Change-Id: I7e9b2ed2e407d8d49c7af736b447d4c6181b0ad8 --- services/surfaceflinger/DisplayDevice.cpp | 3 ++- services/surfaceflinger/DisplayDevice.h | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 27 ++++++++++++++++++++-- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index e5ecf0778..88e0dd70e 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -59,7 +59,8 @@ DisplayDevice::DisplayDevice( const sp& displaySurface, const sp& producer, EGLConfig config) - : mFlinger(flinger), + : lastCompositionHadVisibleLayers(false), + mFlinger(flinger), mType(type), mHwcDisplayId(hwcId), mDisplayToken(displayToken), mDisplaySurface(displaySurface), diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index f750c6c82..620e5983c 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -53,6 +53,7 @@ public: mutable Region swapRegion; // region in screen space Region undefinedRegion; + bool lastCompositionHadVisibleLayers; enum DisplayType { DISPLAY_ID_INVALID = -1, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 08cc50636..13a63c4df 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -881,9 +881,32 @@ void SurfaceFlinger::rebuildLayerStacks() { void SurfaceFlinger::setUpHWComposer() { for (size_t dpy=0 ; dpygetDirtyRegion(false).isEmpty()); + bool dirty = !mDisplays[dpy]->getDirtyRegion(false).isEmpty(); + bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0; + bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers; + + // If nothing has changed (!dirty), don't recompose. + // If something changed, but we don't currently have any visible layers, + // and didn't when we last did a composition, then skip it this time. + // The second rule does two things: + // - When all layers are removed from a display, we'll emit one black + // frame, then nothing more until we get new layers. + // - When a display is created with a private layer stack, we won't + // emit any black frames until a layer is added to the layer stack. + bool mustRecompose = dirty && !(empty && wasEmpty); + + ALOGV_IF(mDisplays[dpy]->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL, + "dpy[%zu]: %s composition (%sdirty %sempty %swasEmpty)", dpy, + mustRecompose ? "doing" : "skipping", + dirty ? "+" : "-", + empty ? "+" : "-", + wasEmpty ? "+" : "-"); + mDisplays[dpy]->beginFrame(mustRecompose); + + if (mustRecompose) { + mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty; + } } HWComposer& hwc(getHwComposer());