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

Commit 57aa1846 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add allocator-v2 extended options to BufferQueue" into main

parents 24a6910f db164ff4
Loading
Loading
Loading
Loading
+114 −8
Original line number Diff line number Diff line
@@ -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
+49 −0
Original line number Diff line number Diff line
@@ -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);
@@ -1532,6 +1559,28 @@ status_t BnGraphicBufferProducer::onTransact(
            reply->writeInt32(result);
            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);
+32 −0
Original line number Diff line number Diff line
@@ -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;
+32 −0
Original line number Diff line number Diff line
/*
 * 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
+11 −0
Original line number Diff line number Diff line
@@ -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
Loading