From b96661ff006d9b0635de11f8be510e19f68d532f Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 17 Sep 2024 11:45:38 -0700 Subject: BufferQueueProducer: queueBuffer() CPU throttling only in async mode BufferQueueProducer throttles an EGL client in queueBuffer() until the GPU has finished the previous frame. This behavior was intended to solve some issues with "swap interval 0" (aka async mode) but was performed all the time. In turn, is prevented a "well behaved" applications from throttling itself, because it would be throttled by BufferQueueProduced before it could get a chance to do so. From the app perspective, eglSwapBuffers() would block. Here we perform the throttling only in async mode, as was the original intention. Applications that don't pace themselves, will still be blocked in dequeueBuffer() eventually, albeit, not necessarily in eglSwapBuffers(). Fix: 359252619 Test: manually tested on pixel8 using AGI and filament sample app Flag: com.android.graphics.libgui.flags.bq_producer_throttles_only_async_mode Change-Id: Ie73848fbf609061bb6feceba5b5c5ad86ec8e07c --- libs/gui/BufferQueueProducer.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'libs/gui/BufferQueueProducer.cpp') diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index a4d105d320..da74e9cde6 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -45,7 +45,10 @@ #include +#include + namespace android { +using namespace com::android::graphics::libgui; // Macros for include BufferQueueCore information in log messages #define BQ_LOGV(x, ...) \ @@ -924,6 +927,7 @@ status_t BufferQueueProducer::queueBuffer(int slot, uint64_t currentFrameNumber = 0; BufferItem item; int connectedApi; + bool enableEglCpuThrottling = true; sp lastQueuedFence; { // Autolock scope @@ -1097,6 +1101,9 @@ status_t BufferQueueProducer::queueBuffer(int slot, VALIDATE_CONSISTENCY(); connectedApi = mCore->mConnectedApi; + if (flags::bq_producer_throttles_only_async_mode()) { + enableEglCpuThrottling = mCore->mAsyncMode || mCore->mDequeueBufferCannotBlock; + } lastQueuedFence = std::move(mLastQueueBufferFence); mLastQueueBufferFence = std::move(acquireFence); @@ -1142,7 +1149,7 @@ status_t BufferQueueProducer::queueBuffer(int slot, } // Wait without lock held - if (connectedApi == NATIVE_WINDOW_API_EGL) { + if (connectedApi == NATIVE_WINDOW_API_EGL && enableEglCpuThrottling) { // 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. -- cgit v1.2.3-59-g8ed1b