diff options
author | Dan Stoza | 2015-04-28 16:42:06 -0500 |
---|---|---|
committer | Dan Stoza | 2015-04-30 17:29:05 -0500 |
commit | 2e36f2283f48ab764b496490c73a132acf21df3a (patch) | |
tree | 9c6a951420250a966b71b12317927c4d1d49114d /services | |
parent | 8de71a2408f632407c25942a39c31f78c7f64ffd (diff) | |
download | frameworks-native-2e36f2283f48ab764b496490c73a132acf21df3a.tar.gz frameworks-native-2e36f2283f48ab764b496490c73a132acf21df3a.tar.xz frameworks-native-2e36f2283f48ab764b496490c73a132acf21df3a.zip |
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
Diffstat (limited to 'services')
-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 2944c6323..9fb94dd3d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp | |||
@@ -127,6 +127,10 @@ void Layer::onFirstRef() { | |||
127 | mSurfaceFlingerConsumer->setContentsChangedListener(this); | 127 | mSurfaceFlingerConsumer->setContentsChangedListener(this); |
128 | mSurfaceFlingerConsumer->setName(mName); | 128 | mSurfaceFlingerConsumer->setName(mName); |
129 | 129 | ||
130 | // Set the shadow queue size to 0 to notify the BufferQueue that we are | ||
131 | // shadowing it | ||
132 | mSurfaceFlingerConsumer->setShadowQueueSize(0); | ||
133 | |||
130 | #ifdef TARGET_DISABLE_TRIPLE_BUFFERING | 134 | #ifdef TARGET_DISABLE_TRIPLE_BUFFERING |
131 | #warning "disabling triple buffering" | 135 | #warning "disabling triple buffering" |
132 | mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2); | 136 | mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2); |
@@ -164,9 +168,10 @@ void Layer::onFrameAvailable(const BufferItem& item) { | |||
164 | { // Autolock scope | 168 | { // Autolock scope |
165 | Mutex::Autolock lock(mQueueItemLock); | 169 | Mutex::Autolock lock(mQueueItemLock); |
166 | mQueueItems.push_back(item); | 170 | mQueueItems.push_back(item); |
171 | mSurfaceFlingerConsumer->setShadowQueueSize(mQueueItems.size()); | ||
172 | android_atomic_inc(&mQueuedFrames); | ||
167 | } | 173 | } |
168 | 174 | ||
169 | android_atomic_inc(&mQueuedFrames); | ||
170 | mFlinger->signalLayerUpdate(); | 175 | mFlinger->signalLayerUpdate(); |
171 | } | 176 | } |
172 | 177 | ||
@@ -1259,14 +1264,39 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) | |||
1259 | // layer update so we check again at the next opportunity. | 1264 | // layer update so we check again at the next opportunity. |
1260 | mFlinger->signalLayerUpdate(); | 1265 | mFlinger->signalLayerUpdate(); |
1261 | return outDirtyRegion; | 1266 | return outDirtyRegion; |
1267 | } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) { | ||
1268 | // If the buffer has been rejected, remove it from the shadow queue | ||
1269 | // and return early | ||
1270 | Mutex::Autolock lock(mQueueItemLock); | ||
1271 | |||
1272 | // Update the BufferQueue with the new shadow queue size after | ||
1273 | // dropping this item | ||
1274 | mQueueItems.removeAt(0); | ||
1275 | mSurfaceFlingerConsumer->setShadowQueueSize(mQueueItems.size()); | ||
1276 | |||
1277 | android_atomic_dec(&mQueuedFrames); | ||
1278 | return outDirtyRegion; | ||
1262 | } | 1279 | } |
1263 | 1280 | ||
1264 | // Remove this buffer from our internal queue tracker | ||
1265 | { // Autolock scope | 1281 | { // Autolock scope |
1282 | auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber(); | ||
1283 | |||
1266 | Mutex::Autolock lock(mQueueItemLock); | 1284 | Mutex::Autolock lock(mQueueItemLock); |
1285 | |||
1286 | // Remove any stale buffers that have been dropped during | ||
1287 | // updateTexImage | ||
1288 | while (mQueueItems[0].mFrameNumber != currentFrameNumber) { | ||
1289 | mQueueItems.removeAt(0); | ||
1290 | android_atomic_dec(&mQueuedFrames); | ||
1291 | } | ||
1292 | |||
1293 | // Update the BufferQueue with our new shadow queue size, since we | ||
1294 | // have removed at least one item | ||
1267 | mQueueItems.removeAt(0); | 1295 | mQueueItems.removeAt(0); |
1296 | mSurfaceFlingerConsumer->setShadowQueueSize(mQueueItems.size()); | ||
1268 | } | 1297 | } |
1269 | 1298 | ||
1299 | |||
1270 | // Decrement the queued-frames count. Signal another event if we | 1300 | // Decrement the queued-frames count. Signal another event if we |
1271 | // have more frames pending. | 1301 | // have more frames pending. |
1272 | if (android_atomic_dec(&mQueuedFrames) > 1) { | 1302 | if (android_atomic_dec(&mQueuedFrames) > 1) { |
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp index 19c497a5d..a9a295882 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp +++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp | |||
@@ -74,7 +74,7 @@ status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter, | |||
74 | int buf = item.mBuf; | 74 | int buf = item.mBuf; |
75 | if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) { | 75 | if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) { |
76 | releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, EGL_NO_SYNC_KHR); | 76 | releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, EGL_NO_SYNC_KHR); |
77 | return NO_ERROR; | 77 | return BUFFER_REJECTED; |
78 | } | 78 | } |
79 | 79 | ||
80 | // Release the previous buffer. | 80 | // Release the previous buffer. |
@@ -125,6 +125,10 @@ sp<NativeHandle> SurfaceFlingerConsumer::getSidebandStream() const { | |||
125 | return mConsumer->getSidebandStream(); | 125 | return mConsumer->getSidebandStream(); |
126 | } | 126 | } |
127 | 127 | ||
128 | void SurfaceFlingerConsumer::setShadowQueueSize(size_t size) { | ||
129 | mConsumer->setShadowQueueSize(size); | ||
130 | } | ||
131 | |||
128 | // We need to determine the time when a buffer acquired now will be | 132 | // We need to determine the time when a buffer acquired now will be |
129 | // displayed. This can be calculated: | 133 | // displayed. This can be calculated: |
130 | // time when previous buffer's actual-present fence was signaled | 134 | // time when previous buffer's actual-present fence was signaled |
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h index 1aaba1884..a90a8b931 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.h +++ b/services/surfaceflinger/SurfaceFlingerConsumer.h | |||
@@ -28,6 +28,8 @@ namespace android { | |||
28 | */ | 28 | */ |
29 | class SurfaceFlingerConsumer : public GLConsumer { | 29 | class SurfaceFlingerConsumer : public GLConsumer { |
30 | public: | 30 | public: |
31 | static const status_t BUFFER_REJECTED = UNKNOWN_ERROR + 8; | ||
32 | |||
31 | struct ContentsChangedListener: public FrameAvailableListener { | 33 | struct ContentsChangedListener: public FrameAvailableListener { |
32 | virtual void onSidebandStreamChanged() = 0; | 34 | virtual void onSidebandStreamChanged() = 0; |
33 | }; | 35 | }; |
@@ -68,6 +70,9 @@ public: | |||
68 | 70 | ||
69 | sp<NativeHandle> getSidebandStream() const; | 71 | sp<NativeHandle> getSidebandStream() const; |
70 | 72 | ||
73 | // See IGraphicBufferConsumer::setShadowQueueSize | ||
74 | void setShadowQueueSize(size_t size); | ||
75 | |||
71 | nsecs_t computeExpectedPresent(const DispSync& dispSync); | 76 | nsecs_t computeExpectedPresent(const DispSync& dispSync); |
72 | 77 | ||
73 | private: | 78 | private: |