summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Dan Stoza <stoza@google.com> 2014-02-04 16:22:36 -0800
committer Andy McFadden <fadden@android.com> 2014-04-22 16:19:02 -0700
commitf3c07d4f70f33c2fe5b14ca8fbcdfa4133cc72c7 (patch)
tree8b3fccb42c2dd684ca7e5a295bf7cde91069a560
parentcf818ebbf07c6a20ef48d71bf82f8d4bdf3a398c (diff)
Fix virtual display nesting
This fixes the cycling rendering loop caused by nesting virtual displays by preventing them from recomposing if their contents haven't changed. (cherry-pick from master I600365c0fd5d3ad93e04295d26cf9de177ffc79b) Bug: 12101046 Change-Id: I6182993d53537781aedb522f97a50f06eed8b80f
-rw-r--r--services/surfaceflinger/DisplayDevice.cpp4
-rw-r--r--services/surfaceflinger/DisplayDevice.h4
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplaySurface.h4
-rw-r--r--services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp2
-rw-r--r--services/surfaceflinger/DisplayHardware/FramebufferSurface.h2
-rw-r--r--services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp35
-rw-r--r--services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h4
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp13
8 files changed, 48 insertions, 20 deletions
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 0d0f98d899..e5ecf07780 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -199,8 +199,8 @@ void DisplayDevice::flip(const Region& dirty) const
mPageFlipCount++;
}
-status_t DisplayDevice::beginFrame() const {
- return mDisplaySurface->beginFrame();
+status_t DisplayDevice::beginFrame(bool mustRecompose) const {
+ return mDisplaySurface->beginFrame(mustRecompose);
}
status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const {
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 01a9d2efc3..f750c6c827 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -124,7 +124,9 @@ public:
int32_t getHwcDisplayId() const { return mHwcDisplayId; }
const wp<IBinder>& getDisplayToken() const { return mDisplayToken; }
- status_t beginFrame() const;
+ // We pass in mustRecompose so we can keep VirtualDisplaySurface's state
+ // machine happy without actually queueing a buffer if nothing has changed
+ status_t beginFrame(bool mustRecompose) const;
status_t prepareFrame(const HWComposer& hwc) const;
void swapBuffers(HWComposer& hwc) const;
diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
index 48bf3f2868..1db3eb8a8c 100644
--- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
@@ -33,7 +33,9 @@ public:
// beginFrame is called at the beginning of the composition loop, before
// the configuration is known. The DisplaySurface should do anything it
// needs to do to enable HWComposer to decide how to compose the frame.
- virtual status_t beginFrame() = 0;
+ // We pass in mustRecompose so we can keep VirtualDisplaySurface's state
+ // machine happy without actually queueing a buffer if nothing has changed.
+ virtual status_t beginFrame(bool mustRecompose) = 0;
// prepareFrame is called after the composition configuration is known but
// before composition takes place. The DisplaySurface can use the
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 8c634ed648..0f34764bd3 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -68,7 +68,7 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp,
mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
}
-status_t FramebufferSurface::beginFrame() {
+status_t FramebufferSurface::beginFrame(bool mustRecompose) {
return NO_ERROR;
}
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 1d67446b94..ba72ce38b8 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -39,7 +39,7 @@ class FramebufferSurface : public ConsumerBase,
public:
FramebufferSurface(HWComposer& hwc, int disp, const sp<IGraphicBufferConsumer>& consumer);
- virtual status_t beginFrame();
+ virtual status_t beginFrame(bool mustRecompose);
virtual status_t prepareFrame(CompositionType compositionType);
virtual status_t compositionComplete();
virtual status_t advanceFrame();
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index d7fef8c1e1..a1820abc63 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -56,7 +56,8 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
mOutputUsage(GRALLOC_USAGE_HW_COMPOSER),
mProducerSlotSource(0),
mDbgState(DBG_STATE_IDLE),
- mDbgLastCompositionType(COMPOSITION_UNKNOWN)
+ mDbgLastCompositionType(COMPOSITION_UNKNOWN),
+ mMustRecompose(false)
{
mSource[SOURCE_SINK] = sink;
mSource[SOURCE_SCRATCH] = bq;
@@ -92,10 +93,12 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
VirtualDisplaySurface::~VirtualDisplaySurface() {
}
-status_t VirtualDisplaySurface::beginFrame() {
+status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) {
if (mDisplayId < 0)
return NO_ERROR;
+ mMustRecompose = mustRecompose;
+
VDS_LOGW_IF(mDbgState != DBG_STATE_IDLE,
"Unexpected beginFrame() in %s state", dbgStateStr());
mDbgState = DBG_STATE_BEGUN;
@@ -228,16 +231,24 @@ void VirtualDisplaySurface::onFrameCommitted() {
QueueBufferOutput qbo;
sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId);
VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot);
- status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
- QueueBufferInput(
- systemTime(), false /* isAutoTimestamp */,
- Rect(mSinkBufferWidth, mSinkBufferHeight),
- NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */,
- true /* async*/,
- outFence),
- &qbo);
- if (result == NO_ERROR) {
- updateQueueBufferOutput(qbo);
+ if (mMustRecompose) {
+ status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
+ QueueBufferInput(
+ systemTime(), false /* isAutoTimestamp */,
+ Rect(mSinkBufferWidth, mSinkBufferHeight),
+ NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */,
+ true /* async*/,
+ outFence),
+ &qbo);
+ if (result == NO_ERROR) {
+ updateQueueBufferOutput(qbo);
+ }
+ } else {
+ // If the surface hadn't actually been updated, then we only went
+ // through the motions of updating the display to keep our state
+ // machine happy. We cancel the buffer to avoid triggering another
+ // re-composition and causing an infinite loop.
+ mSource[SOURCE_SINK]->cancelBuffer(sslot, outFence);
}
}
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 1e85ac4bdb..68999049d0 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -79,7 +79,7 @@ public:
//
// DisplaySurface interface
//
- virtual status_t beginFrame();
+ virtual status_t beginFrame(bool mustRecompose);
virtual status_t prepareFrame(CompositionType compositionType);
virtual status_t compositionComplete();
virtual status_t advanceFrame();
@@ -222,6 +222,8 @@ private:
const char* dbgStateStr() const;
static const char* dbgSourceStr(Source s);
+
+ bool mMustRecompose;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 86be6c3f5c..1a9a6945b4 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -881,7 +881,9 @@ void SurfaceFlinger::rebuildLayerStacks() {
void SurfaceFlinger::setUpHWComposer() {
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- mDisplays[dpy]->beginFrame();
+ bool mustRecompose =
+ !(mDisplays[dpy]->getDirtyRegion(false).isEmpty());
+ mDisplays[dpy]->beginFrame(mustRecompose);
}
HWComposer& hwc(getHwComposer());
@@ -1499,6 +1501,15 @@ void SurfaceFlinger::invalidateHwcGeometry()
void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
const Region& inDirtyRegion)
{
+ // We only need to actually compose the display if:
+ // 1) It is being handled by hardware composer, which may need this to
+ // keep its virtual display state machine in sync, or
+ // 2) There is work to be done (the dirty region isn't empty)
+ bool isHwcDisplay = hw->getHwcDisplayId() >= 0;
+ if (!isHwcDisplay && inDirtyRegion.isEmpty()) {
+ return;
+ }
+
Region dirtyRegion(inDirtyRegion);
// compute the invalid region