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();