summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorDan Stoza <stoza@google.com>2015-05-13 17:15:45 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-05-13 17:15:45 +0000
commit119a03c5a2faee9c40efd53c7d198d9173aba493 (patch)
tree2ecb67f04eab279198bbde5595289330646f63e4 /services
parentc53bc80b624e63f0c65fa3137465c984c8cc8e5f (diff)
parent09d561dbee9a28db9632ff3d51f633c18aefe023 (diff)
downloadframeworks_native-119a03c5a2faee9c40efd53c7d198d9173aba493.zip
frameworks_native-119a03c5a2faee9c40efd53c7d198d9173aba493.tar.gz
frameworks_native-119a03c5a2faee9c40efd53c7d198d9173aba493.tar.bz2
am 09d561db: Merge "Fix PTS handling for buffer replacement" into mnc-dev
* commit '09d561dbee9a28db9632ff3d51f633c18aefe023': Fix PTS handling for buffer replacement
Diffstat (limited to 'services')
-rw-r--r--services/surfaceflinger/Layer.cpp61
-rw-r--r--services/surfaceflinger/Layer.h2
-rw-r--r--services/surfaceflinger/SurfaceFlingerConsumer.cpp14
-rw-r--r--services/surfaceflinger/SurfaceFlingerConsumer.h9
4 files changed, 58 insertions, 28 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 7b104c3..2b733e9 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());
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 0b4c640..947da85 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -416,7 +416,9 @@ private:
// Local copy of the queued contents of the incoming BufferQueue
mutable Mutex mQueueItemLock;
+ Condition mQueueItemCondition;
Vector<BufferItem> mQueueItems;
+ uint64_t mLastFrameNumberReceived;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index a9a2958..ed1f31b 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -32,7 +32,7 @@ namespace android {
// ---------------------------------------------------------------------------
status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,
- const DispSync& dispSync)
+ const DispSync& dispSync, uint64_t maxFrameNumber)
{
ATRACE_CALL();
ALOGV("updateTexImage");
@@ -54,7 +54,8 @@ status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,
// Acquire the next buffer.
// In asynchronous mode the list is guaranteed to be one buffer
// deep, while in synchronous mode we use the oldest buffer.
- err = acquireBufferLocked(&item, computeExpectedPresent(dispSync));
+ err = acquireBufferLocked(&item, computeExpectedPresent(dispSync),
+ maxFrameNumber);
if (err != NO_ERROR) {
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
err = NO_ERROR;
@@ -104,8 +105,9 @@ status_t SurfaceFlingerConsumer::bindTextureImage()
}
status_t SurfaceFlingerConsumer::acquireBufferLocked(BufferItem* item,
- nsecs_t presentWhen) {
- status_t result = GLConsumer::acquireBufferLocked(item, presentWhen);
+ nsecs_t presentWhen, uint64_t maxFrameNumber) {
+ status_t result = GLConsumer::acquireBufferLocked(item, presentWhen,
+ maxFrameNumber);
if (result == NO_ERROR) {
mTransformToDisplayInverse = item->mTransformToDisplayInverse;
mSurfaceDamage = item->mSurfaceDamage;
@@ -125,10 +127,6 @@ sp<NativeHandle> SurfaceFlingerConsumer::getSidebandStream() const {
return mConsumer->getSidebandStream();
}
-void SurfaceFlingerConsumer::setShadowQueueSize(size_t size) {
- mConsumer->setShadowQueueSize(size);
-}
-
// We need to determine the time when a buffer acquired now will be
// displayed. This can be calculated:
// time when previous buffer's actual-present fence was signaled
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index a90a8b9..779e5b7 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -49,13 +49,15 @@ public:
virtual ~BufferRejecter() { }
};
- virtual status_t acquireBufferLocked(BufferItem *item, nsecs_t presentWhen);
+ virtual status_t acquireBufferLocked(BufferItem *item, nsecs_t presentWhen,
+ uint64_t maxFrameNumber = 0) override;
// This version of updateTexImage() takes a functor that may be used to
// reject the newly acquired buffer. Unlike the GLConsumer version,
// this does not guarantee that the buffer has been bound to the GL
// texture.
- status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync);
+ status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync,
+ uint64_t maxFrameNumber = 0);
// See GLConsumer::bindTextureImageLocked().
status_t bindTextureImage();
@@ -70,9 +72,6 @@ public:
sp<NativeHandle> getSidebandStream() const;
- // See IGraphicBufferConsumer::setShadowQueueSize
- void setShadowQueueSize(size_t size);
-
nsecs_t computeExpectedPresent(const DispSync& dispSync);
private: