summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorDan Stoza2015-04-28 16:42:06 -0500
committerDan Stoza2015-04-30 17:29:05 -0500
commit2e36f2283f48ab764b496490c73a132acf21df3a (patch)
tree9c6a951420250a966b71b12317927c4d1d49114d /libs
parent8de71a2408f632407c25942a39c31f78c7f64ffd (diff)
downloadframeworks-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 'libs')
-rw-r--r--libs/gui/BufferQueueConsumer.cpp22
-rw-r--r--libs/gui/BufferQueueCore.cpp4
-rw-r--r--libs/gui/IGraphicBufferConsumer.cpp18
3 files changed, 43 insertions, 1 deletions
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index c7d5e0032..2deef0e77 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -89,7 +89,20 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
89 // the timestamps are being auto-generated by Surface. If the app isn't 89 // the timestamps are being auto-generated by Surface. If the app isn't
90 // generating timestamps explicitly, it probably doesn't want frames to 90 // generating timestamps explicitly, it probably doesn't want frames to
91 // be discarded based on them. 91 // be discarded based on them.
92 //
93 // If the consumer is shadowing our queue, we also make sure that we
94 // don't drop so many buffers that the consumer hasn't received the
95 // onFrameAvailable callback for the buffer it acquires. That is, we
96 // want the buffer we return to be in the consumer's shadow queue.
97 size_t droppableBuffers = mCore->mConsumerShadowQueueSize > 1 ?
98 mCore->mConsumerShadowQueueSize - 1 : 0;
92 while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) { 99 while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
100 if (mCore->mConsumerHasShadowQueue && droppableBuffers == 0) {
101 BQ_LOGV("acquireBuffer: no droppable buffers in consumer's"
102 " shadow queue, continuing");
103 break;
104 }
105
93 // If entry[1] is timely, drop entry[0] (and repeat). We apply an 106 // If entry[1] is timely, drop entry[0] (and repeat). We apply an
94 // additional criterion here: we only drop the earlier buffer if our 107 // additional criterion here: we only drop the earlier buffer if our
95 // desiredPresent falls within +/- 1 second of the expected present. 108 // desiredPresent falls within +/- 1 second of the expected present.
@@ -124,6 +137,7 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
124 } 137 }
125 mCore->mQueue.erase(front); 138 mCore->mQueue.erase(front);
126 front = mCore->mQueue.begin(); 139 front = mCore->mQueue.begin();
140 --droppableBuffers;
127 } 141 }
128 142
129 // See if the front buffer is due 143 // See if the front buffer is due
@@ -537,6 +551,14 @@ sp<NativeHandle> BufferQueueConsumer::getSidebandStream() const {
537 return mCore->mSidebandStream; 551 return mCore->mSidebandStream;
538} 552}
539 553
554void BufferQueueConsumer::setShadowQueueSize(size_t size) {
555 ATRACE_CALL();
556 BQ_LOGV("setShadowQueueSize: %zu", size);
557 Mutex::Autolock lock(mCore->mMutex);
558 mCore->mConsumerHasShadowQueue = true;
559 mCore->mConsumerShadowQueueSize = size;
560}
561
540void BufferQueueConsumer::dump(String8& result, const char* prefix) const { 562void BufferQueueConsumer::dump(String8& result, const char* prefix) const {
541 mCore->dump(result, prefix); 563 mCore->dump(result, prefix);
542} 564}
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index 887f2cbf0..d0f7afad4 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -71,7 +71,9 @@ BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
71 mIsAllocating(false), 71 mIsAllocating(false),
72 mIsAllocatingCondition(), 72 mIsAllocatingCondition(),
73 mAllowAllocation(true), 73 mAllowAllocation(true),
74 mBufferAge(0) 74 mBufferAge(0),
75 mConsumerHasShadowQueue(false),
76 mConsumerShadowQueueSize(0)
75{ 77{
76 if (allocator == NULL) { 78 if (allocator == NULL) {
77 sp<ISurfaceComposer> composer(ComposerService::getComposerService()); 79 sp<ISurfaceComposer> composer(ComposerService::getComposerService());
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index 6658ab11d..480dfb646 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -52,6 +52,7 @@ enum {
52 SET_CONSUMER_USAGE_BITS, 52 SET_CONSUMER_USAGE_BITS,
53 SET_TRANSFORM_HINT, 53 SET_TRANSFORM_HINT,
54 GET_SIDEBAND_STREAM, 54 GET_SIDEBAND_STREAM,
55 SET_SHADOW_QUEUE_SIZE,
55 DUMP, 56 DUMP,
56}; 57};
57 58
@@ -269,6 +270,17 @@ public:
269 return stream; 270 return stream;
270 } 271 }
271 272
273 virtual void setShadowQueueSize(size_t size) {
274 Parcel data, reply;
275 data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
276 data.writeInt64(static_cast<int64_t>(size));
277 status_t result = remote()->transact(SET_SHADOW_QUEUE_SIZE, data, &reply);
278 if (result != NO_ERROR) {
279 ALOGE("setShadowQueueSize failed (%d)", result);
280 return;
281 }
282 }
283
272 virtual void dump(String8& result, const char* prefix) const { 284 virtual void dump(String8& result, const char* prefix) const {
273 Parcel data, reply; 285 Parcel data, reply;
274 data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor()); 286 data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
@@ -423,6 +435,12 @@ status_t BnGraphicBufferConsumer::onTransact(
423 } 435 }
424 return NO_ERROR; 436 return NO_ERROR;
425 } 437 }
438 case SET_SHADOW_QUEUE_SIZE: {
439 CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
440 size_t size = static_cast<size_t>(data.readInt64());
441 setShadowQueueSize(size);
442 return NO_ERROR;
443 }
426 case DUMP: { 444 case DUMP: {
427 CHECK_INTERFACE(IGraphicBufferConsumer, data, reply); 445 CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
428 String8 result = data.readString8(); 446 String8 result = data.readString8();