summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorJesse Hall <jessehall@google.com>2014-08-14 15:45:06 -0700
committerJesse Hall <jessehall@google.com>2014-08-19 22:15:43 -0700
commitb7a0549c983bef103ce07eb3af5905febc6e538e (patch)
tree1aacaf9b71a57800fc358fb4f120e3dd4452ac71 /services
parente3d37a7b55f86f5d005dd67f828dcf51fe60c0f6 (diff)
downloadframeworks_native-b7a0549c983bef103ce07eb3af5905febc6e538e.zip
frameworks_native-b7a0549c983bef103ce07eb3af5905febc6e538e.tar.gz
frameworks_native-b7a0549c983bef103ce07eb3af5905febc6e538e.tar.bz2
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
Diffstat (limited to 'services')
-rw-r--r--services/surfaceflinger/DisplayDevice.cpp3
-rw-r--r--services/surfaceflinger/DisplayDevice.h1
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp27
3 files changed, 28 insertions, 3 deletions
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index e5ecf07..88e0dd7 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -59,7 +59,8 @@ DisplayDevice::DisplayDevice(
const sp<DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& 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 f750c6c..620e598 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 08cc506..13a63c4 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 ; dpy<mDisplays.size() ; dpy++) {
- bool mustRecompose =
- !(mDisplays[dpy]->getDirtyRegion(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());