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
This commit is contained in:
parent
e3d37a7b55
commit
b7a0549c98
@ -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),
|
||||
|
@ -53,6 +53,7 @@ public:
|
||||
mutable Region swapRegion;
|
||||
// region in screen space
|
||||
Region undefinedRegion;
|
||||
bool lastCompositionHadVisibleLayers;
|
||||
|
||||
enum DisplayType {
|
||||
DISPLAY_ID_INVALID = -1,
|
||||
|
@ -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());
|
||||
|
Loading…
Reference in New Issue
Block a user