diff options
author | Dan Stoza <stoza@google.com> | 2015-04-28 14:42:06 -0700 |
---|---|---|
committer | Dan Stoza <stoza@google.com> | 2015-05-01 12:23:44 -0700 |
commit | ecc504043fddb7a75042ce402c67aedfac04d5e2 (patch) | |
tree | ef6b8080362a8655a3291e5757dd72d202701898 /services/surfaceflinger | |
parent | 7b2fc930077b1e6ca5946cae6834902318209474 (diff) | |
download | frameworks_native-ecc504043fddb7a75042ce402c67aedfac04d5e2.zip frameworks_native-ecc504043fddb7a75042ce402c67aedfac04d5e2.tar.gz frameworks_native-ecc504043fddb7a75042ce402c67aedfac04d5e2.tar.bz2 |
SurfaceFlinger: Fix PTS on stale buffers
SurfaceFlinger's (Layer's) shadow copy of the BufferQueue queue was
getting out of sync for a few reasons. This change fixes these by
doing the following:
- Adds a check to re-synchronize the shadow copy every time we
successfully acquire a buffer by first dropping stale buffers before
removing the current buffer.
- Avoids trying to perform updates for buffers which have been rejected
(for incorrect dimensions) by SurfaceFlinger.
- Adds IGraphicBufferConsumer::setShadowQueueSize, which allows the
consumer to notify the BufferQueue that it is maintaining a shadow
copy of the queue and prevents it from dropping so many buffers
during acquireBuffer that it ends up returning a buffer for which the
consumer has not yet received an onFrameAvailable call.
Bug: 20096136
Change-Id: I78d0738428005fc19b3be85cc8f1db498043612f
(cherry picked from commit 2e36f2283f48ab764b496490c73a132acf21df3a)
Diffstat (limited to 'services/surfaceflinger')
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 34 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlingerConsumer.cpp | 6 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlingerConsumer.h | 5 |
3 files changed, 42 insertions, 3 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2944c63..9fb94dd 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -127,6 +127,10 @@ 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); @@ -164,9 +168,10 @@ void Layer::onFrameAvailable(const BufferItem& item) { { // Autolock scope Mutex::Autolock lock(mQueueItemLock); mQueueItems.push_back(item); + mSurfaceFlingerConsumer->setShadowQueueSize(mQueueItems.size()); + android_atomic_inc(&mQueuedFrames); } - android_atomic_inc(&mQueuedFrames); mFlinger->signalLayerUpdate(); } @@ -1259,14 +1264,39 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) // layer update so we check again at the next opportunity. mFlinger->signalLayerUpdate(); return outDirtyRegion; + } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) { + // 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; } - // Remove this buffer from our internal queue tracker { // Autolock scope + auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber(); + Mutex::Autolock lock(mQueueItemLock); + + // Remove any stale buffers that have been dropped during + // updateTexImage + while (mQueueItems[0].mFrameNumber != currentFrameNumber) { + mQueueItems.removeAt(0); + 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()); } + // Decrement the queued-frames count. Signal another event if we // have more frames pending. if (android_atomic_dec(&mQueuedFrames) > 1) { diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp index 19c497a..a9a2958 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp +++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp @@ -74,7 +74,7 @@ status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter, int buf = item.mBuf; if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) { releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, EGL_NO_SYNC_KHR); - return NO_ERROR; + return BUFFER_REJECTED; } // Release the previous buffer. @@ -125,6 +125,10 @@ 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 1aaba18..a90a8b9 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.h +++ b/services/surfaceflinger/SurfaceFlingerConsumer.h @@ -28,6 +28,8 @@ namespace android { */ class SurfaceFlingerConsumer : public GLConsumer { public: + static const status_t BUFFER_REJECTED = UNKNOWN_ERROR + 8; + struct ContentsChangedListener: public FrameAvailableListener { virtual void onSidebandStreamChanged() = 0; }; @@ -68,6 +70,9 @@ public: sp<NativeHandle> getSidebandStream() const; + // See IGraphicBufferConsumer::setShadowQueueSize + void setShadowQueueSize(size_t size); + nsecs_t computeExpectedPresent(const DispSync& dispSync); private: |