Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b96661ff authored by Mathias Agopian's avatar Mathias Agopian
Browse files

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
parent dec962bc
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -45,7 +45,10 @@

#include <system/window.h>

#include <com_android_graphics_libgui_flags.h>

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<Fence> 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.
+9 −1
Original line number Diff line number Diff line
@@ -107,3 +107,11 @@ flag {
  bug: "342197849"
  is_fixed_read_only: true
} # wb_libcameraservice

flag {
  name: "bq_producer_throttles_only_async_mode"
  namespace: "core_graphics"
  description: "BufferQueueProducer only CPU throttle on queueBuffer() in async mode."
  bug: "359252619"
  is_fixed_read_only: true
} # bq_producer_throttles_only_async_mode