From 4f9c275b3f43c4f683b4778b3d3c5464d3dad9a0 Mon Sep 17 00:00:00 2001 From: Jim Shargo Date: Tue, 22 Oct 2024 20:29:12 +0000 Subject: libgui: Add unlimited slot support to Surfaces and Consumers Surfaces can now use `setMaxDequeuedBufferCount` with any value when the consumer supports it to give themselves an essentially unlimited number of buffers to use. ConsumerBase and its libgui children have been updated to allow for unlimited buffer slots by default (meaning all users opt into this automatically), and their implementations have been updated to track the new variable slot limit. This is part of go/warren-buffers. Bug: 341359185 Flag: com.android.graphics.libgui.flags.wb_unlimited_slots Test: new tests, old tests Change-Id: I374aa204a2e42a17d95c6e0ffaef2c2caaa9c963 --- libs/gui/Surface.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 5 deletions(-) (limited to 'libs/gui/Surface.cpp') diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index e41f9bbf43..ec23365e1f 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -98,7 +99,10 @@ Surface::Surface(const sp& bufferProducer, bool controll : mGraphicBufferProducer(bufferProducer), #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) mSurfaceDeathListener(nullptr), -#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) +#endif +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS) + mSlots(NUM_BUFFER_SLOTS), +#endif mCrop(Rect::EMPTY_RECT), mBufferAge(0), mGenerationNumber(0), @@ -192,7 +196,7 @@ void Surface::allocateBuffers() { status_t Surface::allowAllocation(bool allowAllocation) { return mGraphicBufferProducer->allowAllocation(allowAllocation); } -#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) +#endif status_t Surface::setGenerationNumber(uint32_t generation) { status_t result = mGraphicBufferProducer->setGenerationNumber(generation); @@ -658,7 +662,11 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { return result; } +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS) + if (buf < 0 || buf >= (int)mSlots.size()) { +#else if (buf < 0 || buf >= NUM_BUFFER_SLOTS) { +#endif ALOGE("dequeueBuffer: IGraphicBufferProducer returned invalid slot number %d", buf); android_errorWriteLog(0x534e4554, "36991414"); // SafetyNet logging return FAILED_TRANSACTION; @@ -757,7 +765,11 @@ status_t Surface::detachBuffer(const sp& buffer) { Mutex::Autolock lock(mMutex); uint64_t bufferId = buffer->getId(); +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS) + for (int slot = 0; slot < (int)mSlots.size(); ++slot) { +#else for (int slot = 0; slot < Surface::NUM_BUFFER_SLOTS; ++slot) { +#endif auto& bufferSlot = mSlots[slot]; if (bufferSlot.buffer != nullptr && bufferSlot.buffer->getId() == bufferId) { bufferSlot.buffer = nullptr; @@ -840,7 +852,11 @@ int Surface::dequeueBuffers(std::vector* buffers) { return output.result; } +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS) + if (output.slot < 0 || output.slot >= (int)mSlots.size()) { +#else if (output.slot < 0 || output.slot >= NUM_BUFFER_SLOTS) { +#endif mGraphicBufferProducer->cancelBuffers(cancelBufferInputs, &cancelBufferOutputs); ALOGE("%s: IGraphicBufferProducer returned invalid slot number %d", __FUNCTION__, output.slot); @@ -1027,7 +1043,11 @@ int Surface::getSlotFromBufferLocked( return BAD_VALUE; } +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS) + for (int i = 0; i < (int)mSlots.size(); i++) { +#else for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { +#endif if (mSlots[i].buffer != nullptr && mSlots[i].buffer->handle == buffer->handle) { return i; @@ -2094,6 +2114,9 @@ int Surface::connect(int api, const sp& listener, bool reportBu mDefaultHeight = output.height; mNextFrameNumber = output.nextFrameNumber; mMaxBufferCount = output.maxBufferCount; +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS) + mIsSlotExpansionAllowed = output.isSlotExpansionAllowed; +#endif // Ignore transform hint if sticky transform is set or transform to display inverse flag is // set. Transform hint should be ignored if the client is expected to always submit buffers @@ -2190,7 +2213,11 @@ int Surface::detachNextBuffer(sp* outBuffer, *outFence = Fence::NO_FENCE; } +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS) + for (int i = 0; i < (int)mSlots.size(); i++) { +#else for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { +#endif if (mSlots[i].buffer != nullptr && mSlots[i].buffer->getId() == buffer->getId()) { if (mReportRemovedBuffers) { @@ -2292,8 +2319,35 @@ int Surface::setMaxDequeuedBufferCount(int maxDequeuedBuffers) { ALOGV("Surface::setMaxDequeuedBufferCount"); Mutex::Autolock lock(mMutex); - status_t err = mGraphicBufferProducer->setMaxDequeuedBufferCount( - maxDequeuedBuffers); +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS) + if (maxDequeuedBuffers > BufferQueueDefs::NUM_BUFFER_SLOTS && !mIsSlotExpansionAllowed) { + return BAD_VALUE; + } + + int minUndequeuedBuffers = 0; + status_t err = mGraphicBufferProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, + &minUndequeuedBuffers); + if (err != OK) { + ALOGE("IGraphicBufferProducer::query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS) returned %s", + strerror(-err)); + return err; + } + + if (maxDequeuedBuffers > (int)mSlots.size()) { + int newSlotCount = minUndequeuedBuffers + maxDequeuedBuffers; + err = mGraphicBufferProducer->extendSlotCount(newSlotCount); + if (err != OK) { + ALOGE("IGraphicBufferProducer::extendSlotCount(%d) returned %s", newSlotCount, + strerror(-err)); + return err; + } + + mSlots.resize(newSlotCount); + } + err = mGraphicBufferProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers); +#else + status_t err = mGraphicBufferProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers); +#endif ALOGE_IF(err, "IGraphicBufferProducer::setMaxDequeuedBufferCount(%d) " "returned %s", maxDequeuedBuffers, strerror(-err)); @@ -2501,7 +2555,11 @@ void Surface::freeAllBuffers() { ALOGE("%s: %zu buffers were freed while being dequeued!", __FUNCTION__, mDequeuedSlots.size()); } +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS) + for (int i = 0; i < (int)mSlots.size(); i++) { +#else for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { +#endif mSlots[i].buffer = nullptr; } } @@ -2510,7 +2568,11 @@ status_t Surface::getAndFlushBuffersFromSlots(const std::vector& slots, std::vector>* outBuffers) { ALOGV("Surface::getAndFlushBuffersFromSlots"); for (int32_t i : slots) { +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS) + if (i < 0 || i >= (int)mSlots.size()) { +#else if (i < 0 || i >= NUM_BUFFER_SLOTS) { +#endif ALOGE("%s: Invalid slotIndex: %d", __FUNCTION__, i); return BAD_VALUE; } @@ -2670,7 +2732,11 @@ status_t Surface::lock( newDirtyRegion.set(bounds); mDirtyRegion.clear(); Mutex::Autolock lock(mMutex); - for (size_t i=0 ; i