From 99a0afbaee9eddabc2b544e3a5c432901c1d498c Mon Sep 17 00:00:00 2001 From: Eric Penner Date: Tue, 30 Sep 2014 11:28:30 -0700 Subject: [PATCH] BufferQueueProducer: Throttle EGL frame production. Throttling was previously controlled by a combination of the driver and the number of buffers in the queue. This patch makes a more consistent trade-off, which allows two GPU frames pending but not three. More buffering could improve throughput in the case of varying frame times, but this also increases latency. Bug: 17502897 Change-Id: I4ee68019ca94c635294c5959931a555a6c4ef2df --- include/gui/BufferQueueProducer.h | 6 ++++++ libs/gui/BufferQueueProducer.cpp | 12 +++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h index 3fc5de2dd..c619a111c 100644 --- a/include/gui/BufferQueueProducer.h +++ b/include/gui/BufferQueueProducer.h @@ -197,6 +197,12 @@ private: uint32_t mStickyTransform; + // This saves the fence from the last queueBuffer, such that the + // next queueBuffer call can throttle buffer production. The prior + // queueBuffer's fence is not nessessarily available elsewhere, + // since the previous buffer might have already been acquired. + sp mLastQueueBufferFence; + }; // class BufferQueueProducer } // namespace android diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index a53775fa7..03bd4fd5b 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -38,7 +38,8 @@ BufferQueueProducer::BufferQueueProducer(const sp& core) : mCore(core), mSlots(core->mSlots), mConsumerName(), - mStickyTransform(0) {} + mStickyTransform(0), + mLastQueueBufferFence(Fence::NO_FENCE) {} BufferQueueProducer::~BufferQueueProducer() {} @@ -644,6 +645,15 @@ status_t BufferQueueProducer::queueBuffer(int slot, ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size()); } // Autolock scope + // Wait without lock held + if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) { + // Waiting here allows for two full buffers to be queued but not a + // third. In the event that frames take varying time, this makes a + // small trade-off in favor of latency rather than throughput. + mLastQueueBufferFence->waitForever("Throttling EGL Production"); + mLastQueueBufferFence = fence; + } + // Call back without lock held if (listener != NULL) { listener->onFrameAvailable();