summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/Layer.cpp
diff options
context:
space:
mode:
author Dan Stoza <stoza@google.com> 2015-05-12 12:56:16 -0700
committer Dan Stoza <stoza@google.com> 2015-05-12 13:10:17 -0700
commita4650a50a0b35e9e4342d6600b6eb24fd94bb8e5 (patch)
tree756ed49e76eb52abc3b1e8ec7cb962b9a627fcc6 /services/surfaceflinger/Layer.cpp
parent2a7dde58036e02b2417e49c8965d4a518d981b0b (diff)
Fix PTS handling for buffer replacement
This changes the way that SurfaceFlinger's shadow buffer management works such that instead of tracking the size of the shadow queue in the BufferQueue, SF tracks the last frame number it has seen, and passes that into the acquireBuffer call. BufferQueueConsumer then ensures that it never returns a buffer newer than that frame number, even if that means that it must return PRESENT_LATER for an otherwise valid buffer. Change-Id: I3fcb45f683ed660c3f18a8b85ae1f8a962ba6f0e
Diffstat (limited to 'services/surfaceflinger/Layer.cpp')
-rw-r--r--services/surfaceflinger/Layer.cpp61
1 files changed, 46 insertions, 15 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 7b104c3dfa..2b733e905f 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -80,7 +80,11 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
mProtectedByApp(false),
mHasSurface(false),
mClientRef(client),
- mPotentialCursor(false)
+ mPotentialCursor(false),
+ mQueueItemLock(),
+ mQueueItemCondition(),
+ mQueueItems(),
+ mLastFrameNumberReceived(0)
{
mCurrentCrop.makeInvalid();
mFlinger->getRenderEngine().genTextures(1, &mTextureName);
@@ -127,10 +131,6 @@ void Layer::onFirstRef() {
mSurfaceFlingerConsumer->setContentsChangedListener(this);
mSurfaceFlingerConsumer->setName(mName);
- // Set the shadow queue size to 0 to notify the BufferQueue that we are
- // shadowing it
- mSurfaceFlingerConsumer->setShadowQueueSize(0);
-
#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
#warning "disabling triple buffering"
mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
@@ -167,9 +167,28 @@ void Layer::onFrameAvailable(const BufferItem& item) {
// Add this buffer from our internal queue tracker
{ // Autolock scope
Mutex::Autolock lock(mQueueItemLock);
+
+ // Reset the frame number tracker when we receive the first buffer after
+ // a frame number reset
+ if (item.mFrameNumber == 1) {
+ mLastFrameNumberReceived = 0;
+ }
+
+ // Ensure that callbacks are handled in order
+ while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
+ status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
+ ms2ns(500));
+ if (result != NO_ERROR) {
+ ALOGE("[%s] Timed out waiting on callback", mName.string());
+ }
+ }
+
mQueueItems.push_back(item);
- mSurfaceFlingerConsumer->setShadowQueueSize(mQueueItems.size());
android_atomic_inc(&mQueuedFrames);
+
+ // Wake up any pending callbacks
+ mLastFrameNumberReceived = item.mFrameNumber;
+ mQueueItemCondition.broadcast();
}
mFlinger->signalLayerUpdate();
@@ -177,11 +196,25 @@ void Layer::onFrameAvailable(const BufferItem& item) {
void Layer::onFrameReplaced(const BufferItem& item) {
Mutex::Autolock lock(mQueueItemLock);
+
+ // Ensure that callbacks are handled in order
+ while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
+ status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
+ ms2ns(500));
+ if (result != NO_ERROR) {
+ ALOGE("[%s] Timed out waiting on callback", mName.string());
+ }
+ }
+
if (mQueueItems.empty()) {
ALOGE("Can't replace a frame on an empty queue");
return;
}
mQueueItems.editItemAt(0) = item;
+
+ // Wake up any pending callbacks
+ mLastFrameNumberReceived = item.mFrameNumber;
+ mQueueItemCondition.broadcast();
}
void Layer::onSidebandStreamChanged() {
@@ -1261,8 +1294,14 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
getProducerStickyTransform() != 0);
+ uint64_t maxFrameNumber = 0;
+ {
+ Mutex::Autolock lock(mQueueItemLock);
+ maxFrameNumber = mLastFrameNumberReceived;
+ }
+
status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
- mFlinger->mPrimaryDispSync);
+ mFlinger->mPrimaryDispSync, maxFrameNumber);
if (updateResult == BufferQueue::PRESENT_LATER) {
// Producer doesn't want buffer to be displayed yet. Signal a
// layer update so we check again at the next opportunity.
@@ -1272,12 +1311,7 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
// If the buffer has been rejected, remove it from the shadow queue
// and return early
Mutex::Autolock lock(mQueueItemLock);
-
- // Update the BufferQueue with the new shadow queue size after
- // dropping this item
mQueueItems.removeAt(0);
- mSurfaceFlingerConsumer->setShadowQueueSize(mQueueItems.size());
-
android_atomic_dec(&mQueuedFrames);
return outDirtyRegion;
}
@@ -1294,10 +1328,7 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
android_atomic_dec(&mQueuedFrames);
}
- // Update the BufferQueue with our new shadow queue size, since we
- // have removed at least one item
mQueueItems.removeAt(0);
- mSurfaceFlingerConsumer->setShadowQueueSize(mQueueItems.size());
}