diff options
author | 2024-04-03 16:59:28 -0400 | |
---|---|---|
committer | 2024-04-16 15:08:53 -0400 | |
commit | db164ff4e1caccc86654a39ac0def4c51e94d1c0 (patch) | |
tree | f54672718b5b4bb21538ef5e63c9e358f2eaa51d | |
parent | a89ee5d3ab56122ad73a3764e04e94dde4adab92 (diff) |
Add allocator-v2 extended options to BufferQueue
Bug: 268382490
Test: libgui_test
Change-Id: If43b31eede87cddfcbfe4b24b53c1bafb453ebf2
-rw-r--r-- | libs/gui/BufferQueueProducer.cpp | 122 | ||||
-rw-r--r-- | libs/gui/IGraphicBufferProducer.cpp | 49 | ||||
-rw-r--r-- | libs/gui/Surface.cpp | 32 | ||||
-rw-r--r-- | libs/gui/include/gui/AdditionalOptions.h | 32 | ||||
-rw-r--r-- | libs/gui/include/gui/BufferQueueCore.h | 11 | ||||
-rw-r--r-- | libs/gui/include/gui/BufferQueueProducer.h | 5 | ||||
-rw-r--r-- | libs/gui/include/gui/BufferSlot.h | 7 | ||||
-rw-r--r-- | libs/gui/include/gui/IGraphicBufferProducer.h | 5 | ||||
-rw-r--r-- | libs/gui/include/gui/Surface.h | 11 | ||||
-rw-r--r-- | libs/gui/libgui_flags.aconfig | 8 | ||||
-rw-r--r-- | libs/gui/tests/Android.bp | 1 | ||||
-rw-r--r-- | libs/gui/tests/BufferQueue_test.cpp | 57 | ||||
-rw-r--r-- | libs/nativewindow/include/system/window.h | 23 | ||||
-rw-r--r-- | libs/ui/GraphicBufferAllocator.cpp | 4 | ||||
-rw-r--r-- | libs/ui/include/ui/Gralloc.h | 2 | ||||
-rw-r--r-- | libs/ui/include/ui/Gralloc5.h | 2 | ||||
-rw-r--r-- | libs/ui/include/ui/GraphicBufferAllocator.h | 2 |
17 files changed, 365 insertions, 8 deletions
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index fb69fda32d..69345a971e 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -423,6 +423,11 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou sp<IConsumerListener> listener; bool callOnFrameDequeued = false; uint64_t bufferId = 0; // Only used if callOnFrameDequeued == true +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + std::vector<gui::AdditionalOptions> allocOptions; + uint32_t allocOptionsGenId = 0; +#endif + { // Autolock scope std::unique_lock<std::mutex> lock(mCore->mMutex); @@ -486,11 +491,17 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou } const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer); - if (mCore->mSharedBufferSlot == found && - buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) { - BQ_LOGE("dequeueBuffer: cannot re-allocate a shared" - "buffer"); + bool needsReallocation = buffer == nullptr || + buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage); + +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + needsReallocation |= mSlots[found].mAdditionalOptionsGenerationId != + mCore->mAdditionalOptionsGenerationId; +#endif + + if (mCore->mSharedBufferSlot == found && needsReallocation) { + BQ_LOGE("dequeueBuffer: cannot re-allocate a shared buffer"); return BAD_VALUE; } @@ -505,9 +516,7 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou mSlots[found].mBufferState.dequeue(); - if ((buffer == nullptr) || - buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) - { + if (needsReallocation) { if (CC_UNLIKELY(ATRACE_ENABLED())) { if (buffer == nullptr) { ATRACE_FORMAT_INSTANT("%s buffer reallocation: null", mConsumerName.c_str()); @@ -530,6 +539,10 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou mSlots[found].mFence = Fence::NO_FENCE; mCore->mBufferAge = 0; mCore->mIsAllocating = true; +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + allocOptions = mCore->mAdditionalOptions; + allocOptionsGenId = mCore->mAdditionalOptionsGenerationId; +#endif returnFlags |= BUFFER_NEEDS_REALLOCATION; } else { @@ -575,9 +588,29 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou if (returnFlags & BUFFER_NEEDS_REALLOCATION) { BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot); + +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + std::vector<GraphicBufferAllocator::AdditionalOptions> tempOptions; + tempOptions.reserve(allocOptions.size()); + for (const auto& it : allocOptions) { + tempOptions.emplace_back(it.name.c_str(), it.value); + } + const GraphicBufferAllocator::AllocationRequest allocRequest = { + .importBuffer = true, + .width = width, + .height = height, + .format = format, + .layerCount = BQ_LAYER_COUNT, + .usage = usage, + .requestorName = {mConsumerName.c_str(), mConsumerName.size()}, + .extras = std::move(tempOptions), + }; + sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(allocRequest); +#else sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(width, height, format, BQ_LAYER_COUNT, usage, {mConsumerName.c_str(), mConsumerName.size()}); +#endif status_t error = graphicBuffer->initCheck(); @@ -587,6 +620,9 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou if (error == NO_ERROR && !mCore->mIsAbandoned) { graphicBuffer->setGenerationNumber(mCore->mGenerationNumber); mSlots[*outSlot].mGraphicBuffer = graphicBuffer; +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + mSlots[*outSlot].mAdditionalOptionsGenerationId = allocOptionsGenId; +#endif callOnFrameDequeued = true; bufferId = mSlots[*outSlot].mGraphicBuffer->getId(); } @@ -1342,6 +1378,9 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, } mCore->mAllowAllocation = true; +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + mCore->mAdditionalOptions.clear(); +#endif VALIDATE_CONSISTENCY(); return status; } @@ -1410,6 +1449,9 @@ status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) { mCore->mSidebandStream.clear(); mCore->mDequeueCondition.notify_all(); mCore->mAutoPrerotation = false; +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + mCore->mAdditionalOptions.clear(); +#endif listener = mCore->mConsumerListener; } else if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) { BQ_LOGE("disconnect: not connected (req=%d)", api); @@ -1462,6 +1504,10 @@ void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height, PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN; uint64_t allocUsage = 0; std::string allocName; +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + std::vector<gui::AdditionalOptions> allocOptions; + uint32_t allocOptionsGenId = 0; +#endif { // Autolock scope std::unique_lock<std::mutex> lock(mCore->mMutex); mCore->waitWhileAllocatingLocked(lock); @@ -1490,14 +1536,42 @@ void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height, allocUsage = usage | mCore->mConsumerUsageBits; allocName.assign(mCore->mConsumerName.c_str(), mCore->mConsumerName.size()); +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + allocOptions = mCore->mAdditionalOptions; + allocOptionsGenId = mCore->mAdditionalOptionsGenerationId; +#endif + mCore->mIsAllocating = true; + } // Autolock scope +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + std::vector<GraphicBufferAllocator::AdditionalOptions> tempOptions; + tempOptions.reserve(allocOptions.size()); + for (const auto& it : allocOptions) { + tempOptions.emplace_back(it.name.c_str(), it.value); + } + const GraphicBufferAllocator::AllocationRequest allocRequest = { + .importBuffer = true, + .width = allocWidth, + .height = allocHeight, + .format = allocFormat, + .layerCount = BQ_LAYER_COUNT, + .usage = allocUsage, + .requestorName = allocName, + .extras = std::move(tempOptions), + }; +#endif + Vector<sp<GraphicBuffer>> buffers; for (size_t i = 0; i < newBufferCount; ++i) { +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(allocRequest); +#else sp<GraphicBuffer> graphicBuffer = new GraphicBuffer( allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT, allocUsage, allocName); +#endif status_t result = graphicBuffer->initCheck(); @@ -1524,8 +1598,12 @@ void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height, PixelFormat checkFormat = format != 0 ? format : mCore->mDefaultBufferFormat; uint64_t checkUsage = usage | mCore->mConsumerUsageBits; + bool allocOptionsChanged = false; +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + allocOptionsChanged = allocOptionsGenId != mCore->mAdditionalOptionsGenerationId; +#endif if (checkWidth != allocWidth || checkHeight != allocHeight || - checkFormat != allocFormat || checkUsage != allocUsage) { + checkFormat != allocFormat || checkUsage != allocUsage || allocOptionsChanged) { // Something changed while we released the lock. Retry. BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying."); mCore->mIsAllocating = false; @@ -1543,6 +1621,9 @@ void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height, mCore->clearBufferSlotLocked(*slot); // Clean up the slot first mSlots[*slot].mGraphicBuffer = buffers[i]; mSlots[*slot].mFence = Fence::NO_FENCE; +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + mSlots[*slot].mAdditionalOptionsGenerationId = allocOptionsGenId; +#endif // freeBufferLocked puts this slot on the free slots list. Since // we then attached a buffer, move the slot to free buffer list. @@ -1778,4 +1859,29 @@ status_t BufferQueueProducer::setFrameRate(float frameRate, int8_t compatibility } #endif +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) +status_t BufferQueueProducer::setAdditionalOptions( + const std::vector<gui::AdditionalOptions>& options) { + ATRACE_CALL(); + BQ_LOGV("setAdditionalOptions, size = %zu", options.size()); + + if (!GraphicBufferAllocator::get().supportsAdditionalOptions()) { + return INVALID_OPERATION; + } + + std::lock_guard<std::mutex> lock(mCore->mMutex); + + if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) { + BQ_LOGE("setAdditionalOptions: BufferQueue not connected, cannot set additional options"); + return NO_INIT; + } + + if (mCore->mAdditionalOptions != options) { + mCore->mAdditionalOptions = options; + mCore->mAdditionalOptionsGenerationId++; + } + return NO_ERROR; +} +#endif + } // namespace android diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index e81c098b85..09144806ee 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -80,6 +80,7 @@ enum { QUERY_MULTIPLE, GET_LAST_QUEUED_BUFFER2, SET_FRAME_RATE, + SET_ADDITIONAL_OPTIONS, }; class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer> @@ -778,6 +779,25 @@ public: return result; } #endif +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + virtual status_t setAdditionalOptions(const std::vector<gui::AdditionalOptions>& options) { + Parcel data, reply; + data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); + if (options.size() > 100) { + return BAD_VALUE; + } + data.writeInt32(options.size()); + for (const auto& it : options) { + data.writeCString(it.name.c_str()); + data.writeInt64(it.value); + } + status_t result = remote()->transact(SET_ADDITIONAL_OPTIONS, data, &reply); + if (result == NO_ERROR) { + result = reply.readInt32(); + } + return result; + } +#endif }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -981,6 +1001,13 @@ status_t IGraphicBufferProducer::setFrameRate(float /*frameRate*/, int8_t /*comp } #endif +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) +status_t IGraphicBufferProducer::setAdditionalOptions(const std::vector<gui::AdditionalOptions>&) { + // No-op for IGBP other than BufferQueue. + return INVALID_OPERATION; +} +#endif + status_t IGraphicBufferProducer::exportToParcel(Parcel* parcel) { status_t res = OK; res = parcel->writeUint32(USE_BUFFER_QUEUE); @@ -1533,6 +1560,28 @@ status_t BnGraphicBufferProducer::onTransact( return NO_ERROR; } #endif +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + case SET_ADDITIONAL_OPTIONS: { + CHECK_INTERFACE(IGraphicBuffer, data, reply); + int optionCount = data.readInt32(); + if (optionCount < 0 || optionCount > 100) { + return BAD_VALUE; + } + std::vector<gui::AdditionalOptions> opts; + opts.reserve(optionCount); + for (int i = 0; i < optionCount; i++) { + const char* name = data.readCString(); + int64_t value = 0; + if (name == nullptr || data.readInt64(&value) != NO_ERROR) { + return BAD_VALUE; + } + opts.emplace_back(name, value); + } + status_t result = setAdditionalOptions(opts); + reply->writeInt32(result); + return NO_ERROR; + } +#endif } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 086544e48a..87fd448f0c 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1475,6 +1475,9 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO: res = dispatchSetFrameTimelineInfo(args); break; + case NATIVE_WINDOW_SET_BUFFERS_ADDITIONAL_OPTIONS: + res = dispatchSetAdditionalOptions(args); + break; default: res = NAME_NOT_FOUND; break; @@ -1833,6 +1836,24 @@ int Surface::dispatchSetFrameTimelineInfo(va_list args) { return setFrameTimelineInfo(nativeWindowFtlInfo.frameNumber, ftlInfo); } +int Surface::dispatchSetAdditionalOptions(va_list args) { + ATRACE_CALL(); + +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + const AHardwareBufferLongOptions* opts = va_arg(args, const AHardwareBufferLongOptions*); + const size_t optsSize = va_arg(args, size_t); + std::vector<gui::AdditionalOptions> convertedOpts; + convertedOpts.reserve(optsSize); + for (size_t i = 0; i < optsSize; i++) { + convertedOpts.emplace_back(opts[i].name, opts[i].value); + } + return setAdditionalOptions(convertedOpts); +#else + (void)args; + return INVALID_OPERATION; +#endif +} + bool Surface::transformToDisplayInverse() const { return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) == NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; @@ -2619,6 +2640,17 @@ status_t Surface::setFrameTimelineInfo(uint64_t /*frameNumber*/, return BAD_VALUE; } +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) +status_t Surface::setAdditionalOptions(const std::vector<gui::AdditionalOptions>& options) { + if (!GraphicBufferAllocator::get().supportsAdditionalOptions()) { + return INVALID_OPERATION; + } + + Mutex::Autolock lock(mMutex); + return mGraphicBufferProducer->setAdditionalOptions(options); +} +#endif + sp<IBinder> Surface::getSurfaceControlHandle() const { Mutex::Autolock lock(mMutex); return mSurfaceControlHandle; diff --git a/libs/gui/include/gui/AdditionalOptions.h b/libs/gui/include/gui/AdditionalOptions.h new file mode 100644 index 0000000000..87cb913675 --- /dev/null +++ b/libs/gui/include/gui/AdditionalOptions.h @@ -0,0 +1,32 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <string> + +namespace android::gui { +// Additional options to pass to AHardwareBuffer_allocateWithOptions. +// See also allocator-v2's BufferDescriptorInfo.aidl +struct AdditionalOptions { + std::string name; + int64_t value; + + bool operator==(const AdditionalOptions& other) const { + return value == other.value && name == other.name; + } +}; +} // namespace android::gui diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h index 22c2be7bc7..bb52c8ec88 100644 --- a/libs/gui/include/gui/BufferQueueCore.h +++ b/libs/gui/include/gui/BufferQueueCore.h @@ -17,6 +17,9 @@ #ifndef ANDROID_GUI_BUFFERQUEUECORE_H #define ANDROID_GUI_BUFFERQUEUECORE_H +#include <com_android_graphics_libgui_flags.h> + +#include <gui/AdditionalOptions.h> #include <gui/BufferItem.h> #include <gui/BufferQueueDefs.h> #include <gui/BufferSlot.h> @@ -357,6 +360,14 @@ private: // This allows the consumer to acquire an additional buffer if that buffer is not droppable and // will eventually be released or acquired by the consumer. bool mAllowExtraAcquire = false; + +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + // Additional options to pass when allocating GraphicBuffers. + // GenerationID changes when the options change, indicating reallocation is required + uint32_t mAdditionalOptionsGenerationId = 0; + std::vector<gui::AdditionalOptions> mAdditionalOptions; +#endif + }; // class BufferQueueCore } // namespace android diff --git a/libs/gui/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h index de47483dca..37a960708c 100644 --- a/libs/gui/include/gui/BufferQueueProducer.h +++ b/libs/gui/include/gui/BufferQueueProducer.h @@ -17,6 +17,7 @@ #ifndef ANDROID_GUI_BUFFERQUEUEPRODUCER_H #define ANDROID_GUI_BUFFERQUEUEPRODUCER_H +#include <gui/AdditionalOptions.h> #include <gui/BufferQueueDefs.h> #include <gui/IGraphicBufferProducer.h> @@ -208,6 +209,10 @@ public: int8_t changeFrameRateStrategy) override; #endif +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + status_t setAdditionalOptions(const std::vector<gui::AdditionalOptions>& options) override; +#endif + protected: // see IGraphicsBufferProducer::setMaxDequeuedBufferCount, but with the ability to retrieve the // total maximum buffer count for the buffer queue (dequeued AND acquired) diff --git a/libs/gui/include/gui/BufferSlot.h b/libs/gui/include/gui/BufferSlot.h index 57704b1d09..5b32710135 100644 --- a/libs/gui/include/gui/BufferSlot.h +++ b/libs/gui/include/gui/BufferSlot.h @@ -17,6 +17,8 @@ #ifndef ANDROID_GUI_BUFFERSLOT_H #define ANDROID_GUI_BUFFERSLOT_H +#include <com_android_graphics_libgui_flags.h> + #include <ui/Fence.h> #include <ui/GraphicBuffer.h> @@ -230,6 +232,11 @@ struct BufferSlot { // producer. If so, it needs to set the BUFFER_NEEDS_REALLOCATION flag when // dequeued to prevent the producer from using a stale cached buffer. bool mNeedsReallocation; + +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + // The generation id of the additional options that mGraphicBuffer was allocated with + uint32_t mAdditionalOptionsGenerationId = 0; +#endif }; } // namespace android diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h index 7639e709ca..8fca9460aa 100644 --- a/libs/gui/include/gui/IGraphicBufferProducer.h +++ b/libs/gui/include/gui/IGraphicBufferProducer.h @@ -31,6 +31,7 @@ #include <ui/Rect.h> #include <ui/Region.h> +#include <gui/AdditionalOptions.h> #include <gui/FrameTimestamps.h> #include <gui/HdrMetadata.h> @@ -684,6 +685,10 @@ public: int8_t changeFrameRateStrategy); #endif +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + virtual status_t setAdditionalOptions(const std::vector<gui::AdditionalOptions>& options); +#endif + struct RequestBufferOutput : public Flattenable<RequestBufferOutput> { RequestBufferOutput() = default; diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 39a59e42aa..bdcaaf2866 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -215,6 +215,16 @@ public: int8_t changeFrameRateStrategy); virtual status_t setFrameTimelineInfo(uint64_t frameNumber, const FrameTimelineInfo& info); +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + /** + * Set additional options to be passed when allocating a buffer. Only valid if IAllocator-V2 + * or newer is available, otherwise will return INVALID_OPERATION. Only allowed to be called + * after connect and options are cleared when disconnect happens. Returns NO_INIT if not + * connected + */ + status_t setAdditionalOptions(const std::vector<gui::AdditionalOptions>& options); +#endif + protected: virtual ~Surface(); @@ -302,6 +312,7 @@ private: int dispatchGetLastQueuedBuffer(va_list args); int dispatchGetLastQueuedBuffer2(va_list args); int dispatchSetFrameTimelineInfo(va_list args); + int dispatchSetAdditionalOptions(va_list args); std::mutex mNameMutex; std::string mName; diff --git a/libs/gui/libgui_flags.aconfig b/libs/gui/libgui_flags.aconfig index 38646992da..a902a8c5cb 100644 --- a/libs/gui/libgui_flags.aconfig +++ b/libs/gui/libgui_flags.aconfig @@ -16,3 +16,11 @@ flag { bug: "310927247" is_fixed_read_only: true } + +flag { + name: "bq_extendedallocate" + namespace: "core_graphics" + description: "Add BQ support for allocate with extended options" + bug: "268382490" + is_fixed_read_only: true +} diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp index 2faa330426..ea8acbbb72 100644 --- a/libs/gui/tests/Android.bp +++ b/libs/gui/tests/Android.bp @@ -24,6 +24,7 @@ cc_test { "-Wextra", "-Wthread-safety", "-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_BQ_SETFRAMERATE=true", + "-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_BQ_EXTENDEDALLOCATE=true", ], srcs: [ diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp index 1ec6f915f7..272c5ed2b4 100644 --- a/libs/gui/tests/BufferQueue_test.cpp +++ b/libs/gui/tests/BufferQueue_test.cpp @@ -28,6 +28,8 @@ #include <ui/GraphicBuffer.h> +#include <android-base/properties.h> + #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <binder/ProcessState.h> @@ -47,6 +49,10 @@ using namespace std::chrono_literals; +static bool IsCuttlefish() { + return ::android::base::GetProperty("ro.product.board", "") == "cutf"; +} + namespace android { using namespace com::android::graphics::libgui; @@ -1439,4 +1445,55 @@ TEST(BufferQueueThreading, TestProducerDequeueConsumerDestroy) { EXPECT_EQ(nullptr, bufferConsumer.get()); } +TEST_F(BufferQueueTest, TestAdditionalOptions) { + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + + sp<BufferItemConsumer> bufferConsumer = + sp<BufferItemConsumer>::make(consumer, GRALLOC_USAGE_SW_READ_OFTEN, 2); + ASSERT_NE(nullptr, bufferConsumer.get()); + sp<Surface> surface = sp<Surface>::make(producer); + native_window_set_buffers_format(surface.get(), PIXEL_FORMAT_RGBA_8888); + native_window_set_buffers_dimensions(surface.get(), 100, 100); + + std::array<AHardwareBufferLongOptions, 1> extras = {{ + {.name = "android.hardware.graphics.common.Dataspace", ADATASPACE_DISPLAY_P3}, + }}; + + ASSERT_EQ(NO_INIT, + native_window_set_buffers_additional_options(surface.get(), extras.data(), + extras.size())); + + if (!IsCuttlefish()) { + GTEST_SKIP() << "Not cuttlefish"; + } + + ASSERT_EQ(OK, native_window_api_connect(surface.get(), NATIVE_WINDOW_API_CPU)); + ASSERT_EQ(OK, + native_window_set_buffers_additional_options(surface.get(), extras.data(), + extras.size())); + + ANativeWindowBuffer* windowBuffer = nullptr; + int fence = -1; + ASSERT_EQ(OK, ANativeWindow_dequeueBuffer(surface.get(), &windowBuffer, &fence)); + + AHardwareBuffer* buffer = ANativeWindowBuffer_getHardwareBuffer(windowBuffer); + ASSERT_TRUE(buffer); + ADataSpace dataSpace = AHardwareBuffer_getDataSpace(buffer); + EXPECT_EQ(ADATASPACE_DISPLAY_P3, dataSpace); + + ANativeWindow_cancelBuffer(surface.get(), windowBuffer, -1); + + // Check that reconnecting properly clears the options + ASSERT_EQ(OK, native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_CPU)); + ASSERT_EQ(OK, native_window_api_connect(surface.get(), NATIVE_WINDOW_API_CPU)); + + ASSERT_EQ(OK, ANativeWindow_dequeueBuffer(surface.get(), &windowBuffer, &fence)); + buffer = ANativeWindowBuffer_getHardwareBuffer(windowBuffer); + ASSERT_TRUE(buffer); + dataSpace = AHardwareBuffer_getDataSpace(buffer); + EXPECT_EQ(ADATASPACE_UNKNOWN, dataSpace); +} + } // namespace android diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index 969a5cff05..33c303ae71 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -41,6 +41,8 @@ #include <system/graphics.h> #include <unistd.h> +#include <vndk/hardware_buffer.h> + // system/window.h is a superset of the vndk and apex apis #include <apex/window.h> #include <vndk/window.h> @@ -257,6 +259,7 @@ enum { NATIVE_WINDOW_SET_QUERY_INTERCEPTOR = 47, /* private */ NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO = 48, /* private */ NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER2 = 49, /* private */ + NATIVE_WINDOW_SET_BUFFERS_ADDITIONAL_OPTIONS = 50, // clang-format on }; @@ -1182,6 +1185,26 @@ static inline int native_window_set_frame_timeline_info( return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO, frameTimelineInfo); } +/** + * native_window_set_buffers_additional_options(..., ExtendableType* additionalOptions, size_t size) + * All buffers dequeued after this call will have the additionalOptions specified. + * + * This must only be called after api_connect, otherwise NO_INIT is returned. The options are + * cleared in api_disconnect & api_connect + * + * If IAllocator is not v2 or newer this method returns INVALID_OPERATION + * + * \return NO_ERROR on success. + * \return NO_INIT if no api is connected + * \return INVALID_OPERATION if additional option support is not available + */ +static inline int native_window_set_buffers_additional_options( + struct ANativeWindow* window, const AHardwareBufferLongOptions* additionalOptions, + size_t additionalOptionsSize) { + return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_ADDITIONAL_OPTIONS, additionalOptions, + additionalOptionsSize); +} + // ------------------------------------------------------------------------------------------------ // Candidates for APEX visibility // These functions are planned to be made stable for APEX modules, but have not diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp index 98082fb81e..1ebe5973fa 100644 --- a/libs/ui/GraphicBufferAllocator.cpp +++ b/libs/ui/GraphicBufferAllocator.cpp @@ -291,5 +291,9 @@ status_t GraphicBufferAllocator::free(buffer_handle_t handle) return NO_ERROR; } +bool GraphicBufferAllocator::supportsAdditionalOptions() const { + return mAllocator->supportsAdditionalOptions(); +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/libs/ui/include/ui/Gralloc.h b/libs/ui/include/ui/Gralloc.h index e6015e0b5e..4167dcbab1 100644 --- a/libs/ui/include/ui/Gralloc.h +++ b/libs/ui/include/ui/Gralloc.h @@ -226,6 +226,8 @@ public: const GraphicBufferAllocator::AllocationRequest&) const { return GraphicBufferAllocator::AllocationResult(UNKNOWN_TRANSACTION); } + + virtual bool supportsAdditionalOptions() const { return false; } }; } // namespace android diff --git a/libs/ui/include/ui/Gralloc5.h b/libs/ui/include/ui/Gralloc5.h index f9e8f5e9fd..5aa5019603 100644 --- a/libs/ui/include/ui/Gralloc5.h +++ b/libs/ui/include/ui/Gralloc5.h @@ -178,6 +178,8 @@ public: [[nodiscard]] GraphicBufferAllocator::AllocationResult allocate( const GraphicBufferAllocator::AllocationRequest&) const override; + bool supportsAdditionalOptions() const override { return true; } + private: const Gralloc5Mapper &mMapper; std::shared_ptr<aidl::android::hardware::graphics::allocator::IAllocator> mAllocator; diff --git a/libs/ui/include/ui/GraphicBufferAllocator.h b/libs/ui/include/ui/GraphicBufferAllocator.h index 8f461e193b..bbb2d77058 100644 --- a/libs/ui/include/ui/GraphicBufferAllocator.h +++ b/libs/ui/include/ui/GraphicBufferAllocator.h @@ -107,6 +107,8 @@ public: void dump(std::string& res, bool less = true) const; static void dumpToSystemLog(bool less = true); + bool supportsAdditionalOptions() const; + protected: struct alloc_rec_t { uint32_t width; |