From 3c25621ad7d13f64d3ab95a27fa970fbc9998f73 Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Fri, 16 Aug 2013 14:55:39 -0700 Subject: [PATCH] Re-enable frame dropping for non-auto timestamps This change adds an entire field to note whether the timestamp was auto-generated by Surface or supplied by the application. The value is used when deciding whether or not to drop frames based on buffer presentation timestamps. If a desired presentation time was set explicitly, BufferQueue will use that value to decide if a frame should be dropped. If the timestamp was generated by Surface at the time the buffer was queued, the timestamp is ignored. Bug 10151804 Change-Id: Ibd571a7578351063b813cbdad2ddbeed70655ba5 --- include/gui/IGraphicBufferConsumer.h | 4 ++++ include/gui/IGraphicBufferProducer.h | 15 +++++++++------ libs/gui/BufferQueue.cpp | 12 ++++++++++-- libs/gui/IGraphicBufferConsumer.cpp | 4 ++++ libs/gui/IGraphicBufferProducer.cpp | 4 ++++ libs/gui/Surface.cpp | 6 ++++-- .../DisplayHardware/VirtualDisplaySurface.cpp | 7 ++++--- 7 files changed, 39 insertions(+), 13 deletions(-) diff --git a/include/gui/IGraphicBufferConsumer.h b/include/gui/IGraphicBufferConsumer.h index 2ad302f48..3327b3772 100644 --- a/include/gui/IGraphicBufferConsumer.h +++ b/include/gui/IGraphicBufferConsumer.h @@ -72,6 +72,10 @@ public: // to set by queueBuffer each time this slot is queued. int64_t mTimestamp; + // mIsAutoTimestamp indicates whether mTimestamp was generated + // automatically when the buffer was queued. + bool mIsAutoTimestamp; + // mFrameNumber is the number of the queued frame for this slot. uint64_t mFrameNumber; diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h index 033c7273c..c3ede5ef7 100644 --- a/include/gui/IGraphicBufferProducer.h +++ b/include/gui/IGraphicBufferProducer.h @@ -108,15 +108,17 @@ public: struct QueueBufferInput : public Flattenable { friend class Flattenable; inline QueueBufferInput(const Parcel& parcel); - inline QueueBufferInput(int64_t timestamp, + inline QueueBufferInput(int64_t timestamp, bool isAutoTimestamp, const Rect& crop, int scalingMode, uint32_t transform, bool async, const sp& fence) - : timestamp(timestamp), crop(crop), scalingMode(scalingMode), - transform(transform), async(async), fence(fence) { } - inline void deflate(int64_t* outTimestamp, Rect* outCrop, - int* outScalingMode, uint32_t* outTransform, bool* outAsync, - sp* outFence) const { + : timestamp(timestamp), isAutoTimestamp(isAutoTimestamp), crop(crop), + scalingMode(scalingMode), transform(transform), async(async), + fence(fence) { } + inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp, + Rect* outCrop, int* outScalingMode, uint32_t* outTransform, + bool* outAsync, sp* outFence) const { *outTimestamp = timestamp; + *outIsAutoTimestamp = bool(isAutoTimestamp); *outCrop = crop; *outScalingMode = scalingMode; *outTransform = transform; @@ -132,6 +134,7 @@ public: private: int64_t timestamp; + int isAutoTimestamp; Rect crop; int scalingMode; uint32_t transform; diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index 033c2a6c4..65007fa24 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -475,10 +475,12 @@ status_t BufferQueue::queueBuffer(int buf, uint32_t transform; int scalingMode; int64_t timestamp; + bool isAutoTimestamp; bool async; sp fence; - input.deflate(×tamp, &crop, &scalingMode, &transform, &async, &fence); + input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, &transform, + &async, &fence); if (fence == NULL) { ST_LOGE("queueBuffer: fence is NULL"); @@ -558,6 +560,7 @@ status_t BufferQueue::queueBuffer(int buf, item.mTransform = transform; item.mScalingMode = scalingMode; item.mTimestamp = timestamp; + item.mIsAutoTimestamp = isAutoTimestamp; item.mFrameNumber = mFrameCounter; item.mBuf = buf; item.mFence = fence; @@ -860,7 +863,12 @@ status_t BufferQueue::acquireBuffer(BufferItem *buffer, nsecs_t expectedPresent) // // NOTE: code assumes monotonic time values from the system clock are // positive. - while (false && mQueue.size() > 1) { + + // Start by checking to see if we can drop frames. We skip this check + // if the timestamps are being auto-generated by Surface -- if the + // app isn't generating timestamps explicitly, they probably don't + // want frames to be discarded based on them. + while (mQueue.size() > 1 && !mQueue[0].mIsAutoTimestamp) { // If entry[1] is timely, drop entry[0] (and repeat). We apply // an additional criteria here: we only drop the earlier buffer if // our desiredPresent falls within +/- 1 second of the expected diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp index 6d65016cf..4db635ca1 100644 --- a/libs/gui/IGraphicBufferConsumer.cpp +++ b/libs/gui/IGraphicBufferConsumer.cpp @@ -43,6 +43,7 @@ IGraphicBufferConsumer::BufferItem::BufferItem() : mTransform(0), mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mTimestamp(0), + mIsAutoTimestamp(false), mFrameNumber(0), mBuf(INVALID_BUFFER_SLOT), mIsDroppable(false), @@ -55,6 +56,7 @@ size_t IGraphicBufferConsumer::BufferItem::getPodSize() const { sizeof(mTransform) + sizeof(mScalingMode) + sizeof(mTimestamp) + + sizeof(mIsAutoTimestamp) + sizeof(mFrameNumber) + sizeof(mBuf) + sizeof(mIsDroppable) + @@ -123,6 +125,7 @@ status_t IGraphicBufferConsumer::BufferItem::flatten( FlattenableUtils::write(buffer, size, mTransform); FlattenableUtils::write(buffer, size, mScalingMode); FlattenableUtils::write(buffer, size, mTimestamp); + FlattenableUtils::write(buffer, size, mIsAutoTimestamp); FlattenableUtils::write(buffer, size, mFrameNumber); FlattenableUtils::write(buffer, size, mBuf); FlattenableUtils::write(buffer, size, mIsDroppable); @@ -163,6 +166,7 @@ status_t IGraphicBufferConsumer::BufferItem::unflatten( FlattenableUtils::read(buffer, size, mTransform); FlattenableUtils::read(buffer, size, mScalingMode); FlattenableUtils::read(buffer, size, mTimestamp); + FlattenableUtils::read(buffer, size, mIsAutoTimestamp); FlattenableUtils::read(buffer, size, mFrameNumber); FlattenableUtils::read(buffer, size, mBuf); FlattenableUtils::read(buffer, size, mIsDroppable); diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index e3d2a20df..3080220f4 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -269,6 +269,7 @@ IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const { return sizeof(timestamp) + + sizeof(isAutoTimestamp) + sizeof(crop) + sizeof(scalingMode) + sizeof(transform) @@ -287,6 +288,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::flatten( return NO_MEMORY; } FlattenableUtils::write(buffer, size, timestamp); + FlattenableUtils::write(buffer, size, isAutoTimestamp); FlattenableUtils::write(buffer, size, crop); FlattenableUtils::write(buffer, size, scalingMode); FlattenableUtils::write(buffer, size, transform); @@ -299,6 +301,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::unflatten( { size_t minNeeded = sizeof(timestamp) + + sizeof(isAutoTimestamp) + sizeof(crop) + sizeof(scalingMode) + sizeof(transform) @@ -309,6 +312,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::unflatten( } FlattenableUtils::read(buffer, size, timestamp); + FlattenableUtils::read(buffer, size, isAutoTimestamp); FlattenableUtils::read(buffer, size, crop); FlattenableUtils::read(buffer, size, scalingMode); FlattenableUtils::read(buffer, size, transform); diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index f3a7e5ea7..b9a12ed9a 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -262,8 +262,10 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) { ALOGV("Surface::queueBuffer"); Mutex::Autolock lock(mMutex); int64_t timestamp; + bool isAutoTimestamp = false; if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) { timestamp = systemTime(SYSTEM_TIME_MONOTONIC); + isAutoTimestamp = true; ALOGV("Surface::queueBuffer making up timestamp: %.2f ms", timestamp / 1000000.f); } else { @@ -281,8 +283,8 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) { sp fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE); IGraphicBufferProducer::QueueBufferOutput output; - IGraphicBufferProducer::QueueBufferInput input(timestamp, crop, mScalingMode, - mTransform, mSwapIntervalZero, fence); + IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp, + crop, mScalingMode, mTransform, mSwapIntervalZero, fence); status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output); if (err != OK) { ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err); diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index 30b00845b..89c87c70f 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -185,7 +185,7 @@ void VirtualDisplaySurface::onFrameCommitted() { sp outFence = mHwc.getLastRetireFence(mDisplayId); VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot); status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot, - QueueBufferInput(systemTime(), + QueueBufferInput(systemTime(), false, Rect(mSinkBufferWidth, mSinkBufferHeight), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, outFence), &qbo); @@ -309,12 +309,13 @@ status_t VirtualDisplaySurface::queueBuffer(int pslot, // Extract the GLES release fence for HWC to acquire int64_t timestamp; + bool isAutoTimestamp; Rect crop; int scalingMode; uint32_t transform; bool async; - input.deflate(×tamp, &crop, &scalingMode, &transform, - &async, &mFbFence); + input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, + &transform, &async, &mFbFence); mFbProducerSlot = pslot; }