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

Commit 44abd2d5 authored by Sungtak Lee's avatar Sungtak Lee
Browse files

GraphicsTracker: allocate from ReleaseSurface after stop

After stop, GraphicsTracker allocates a buffer directly via
AHardwareBuffer_allocate. But AHardwareBuffer_allocate has friction
regarding usage and format with gralloc allocate.
So Use a Surface to allocate after stop.

Bug: 382882341
Flag: EXEMPT bugfix
Test: atest WidevineAV1PlaybackTests#testL1With240P24UsingExo2Extractor
Change-Id: I5af7a6fbd91442666ce19a0fa52236d17277a9ac
parent b9ff5994
Loading
Loading
Loading
Loading
+104 −4
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@
#include <fcntl.h>
#include <unistd.h>

#include <gui/BufferItemConsumer.h>
#include <gui/BufferQueue.h>
#include <gui/Surface.h>
#include <media/stagefright/foundation/ADebug.h>
#include <private/android/AHardwareBufferHelpers.h>
#include <vndk/hardware_buffer.h>
@@ -57,6 +60,90 @@ c2_status_t retrieveAHardwareBufferId(const C2ConstGraphicBlock &blk, uint64_t *

} // anonymous namespace

using ::android::BufferQueue;
using ::android::BufferItemConsumer;
using ::android::ConsumerListener;
using ::android::IConsumerListener;
using ::android::IGraphicBufferProducer;
using ::android::IGraphicBufferConsumer;
using ::android::Surface;

class GraphicsTracker::PlaceHolderSurface {
public:
    static const int kMaxAcquiredBuffer = 2;
    // Enough number to allocate in stop/release status.
    static const int kMaxDequeuedBuffer = 16;

    explicit PlaceHolderSurface(uint64_t usage) : mUsage(usage) {}

    ~PlaceHolderSurface() {
        if (mInit == C2_NO_INIT) {
            return;
        }
        if (mSurface) {
            mSurface->disconnect(NATIVE_WINDOW_API_MEDIA);
        }
    }

    c2_status_t allocate(uint32_t width, uint32_t height,
            uint32_t format, uint64_t usage,
            AHardwareBuffer **pBuf, sp<Fence> *fence) {
        std::unique_lock<std::mutex> l(mLock);
        if (mInit == C2_NO_INIT) {
            mInit = init();
        }

        if (!mBufferItemConsumer || !mSurface) {
            ALOGE("PlaceHolderSurface not properly initialized");
            return C2_CORRUPTED;
        }

        native_window_set_usage(mSurface.get(), usage);
        native_window_set_buffers_format(mSurface.get(), format);
        native_window_set_buffers_dimensions(mSurface.get(), width, height);

        ::android::status_t res;
        std::vector<Surface::BatchBuffer> buffers(1);
        res = mSurface->dequeueBuffers(&buffers);
        if (res != ::android::OK) {
            ALOGE("dequeueBuffers failed from PlaceHolderSurface %d", res);
            return C2_CORRUPTED;
        }
        sp<GraphicBuffer> gb = GraphicBuffer::from(buffers[0].buffer);
        *pBuf = AHardwareBuffer_from_GraphicBuffer(gb.get());
        AHardwareBuffer_acquire(*pBuf);
        *fence = new Fence(buffers[0].fenceFd);
        return C2_OK;
    }

private:
    uint64_t mUsage;
    sp<Surface> mSurface;
    sp<BufferItemConsumer> mBufferItemConsumer;
    c2_status_t mInit = C2_NO_INIT;
    std::mutex mLock;

    c2_status_t init() {
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
        mBufferItemConsumer =
                sp<BufferItemConsumer>::make(mUsage, kMaxAcquiredBuffer);
        mSurface = mBufferItemConsumer->getSurface();
#else
        sp<IGraphicBufferProducer> producer;
        sp<IGraphicBufferConsumer> consumer;
        BufferQueue::createBufferQueue(&producer, &consumer);
        mBufferItemConsumer = sp<BufferItemConsumer>::make(consumer, mUsage);
        mSurface = sp<Surface>::make(producer, false);
#endif
        if (mSurface) {
            mSurface->connect(NATIVE_WINDOW_API_MEDIA, nullptr);
            mSurface->setMaxDequeuedBufferCount(kMaxDequeuedBuffer);
        }
        return C2_OK;
    }
};


GraphicsTracker::BufferItem::BufferItem(
        uint32_t generation, int slot, const sp<GraphicBuffer>& buf, const sp<Fence>& fence) :
        mInit{false}, mGeneration{generation}, mSlot{slot} {
@@ -256,9 +343,13 @@ c2_status_t GraphicsTracker::configureGraphics(
    // to the old surface in MediaCodec and allocate from the new surface from
    // GraphicsTracker cannot be synchronized properly.
    uint64_t bqId{0ULL};
    uint64_t bqUsage{0ULL};
    ::android::status_t ret = ::android::OK;
    if (igbp) {
        ret = igbp->getUniqueId(&bqId);
        if (ret == ::android::OK) {
            (void)igbp->getConsumerUsage(&bqUsage);
        }
    }
    if (ret != ::android::OK ||
            prevCache->mGeneration == generation) {
@@ -287,7 +378,8 @@ c2_status_t GraphicsTracker::configureGraphics(
    }
    ALOGD("new surface configured with id:%llu gen:%lu maxDequeue:%d",
          (unsigned long long)bqId, (unsigned long)generation, prevDequeueCommitted);
    std::shared_ptr<BufferCache> newCache = std::make_shared<BufferCache>(bqId, generation, igbp);
    std::shared_ptr<BufferCache> newCache =
            std::make_shared<BufferCache>(bqId, bqUsage, generation, igbp);
    {
        std::unique_lock<std::mutex> l(mLock);
        mInConfig = false;
@@ -501,6 +593,9 @@ void GraphicsTracker::onRequestStop() {
    if (mStopRequested) {
        return;
    }
    if (mBufferCache && mBufferCache->mBqId != 0) {
        mReleaseSurface.reset(new PlaceHolderSurface(mBufferCache->mUsage));
    }
    mStopRequested = true;
    writeIncDequeueableLocked(kMaxDequeueMax - 1);
}
@@ -764,9 +859,7 @@ c2_status_t GraphicsTracker::_allocateDirect(
        }
    }

    int alloced = mAllocAfterStopRequested++;
    *rFence = Fence::NO_FENCE;
    ALOGD("_allocateDirect() allocated %d buffer", alloced);
    return C2_OK;
}

@@ -783,7 +876,14 @@ c2_status_t GraphicsTracker::allocate(
        std::unique_lock<std::mutex> l(mLock);
        if (mStopRequested) {
            l.unlock();
            if (mReleaseSurface) {
                res = mReleaseSurface->allocate(width, height, format, usage, buf, rFence);
            } else {
                res = _allocateDirect(width, height, format, usage, buf, rFence);
            }
            if (res == C2_OK) {
                ALOGD("allocateed %d buffer after stop", ++mAllocAfterStopRequested);
            }
            // Delay a little bit for HAL to receive stop()/release() request.
            ::usleep(kAllocateDirectDelayUs);
            return res;
+10 −3
Original line number Diff line number Diff line
@@ -224,6 +224,7 @@ private:
        static constexpr int kNumSlots = ::android::BufferQueueDefs::NUM_BUFFER_SLOTS;

        uint64_t mBqId;
        uint64_t mUsage;
        uint32_t mGeneration;
        ::android::sp<IGraphicBufferProducer> mIgbp;

@@ -245,9 +246,11 @@ private:

        std::atomic<int> mNumAttached;

        BufferCache() : mBqId{0ULL}, mGeneration{0}, mIgbp{nullptr}, mNumAttached{0} {}
        BufferCache(uint64_t bqId, uint32_t generation, const sp<IGraphicBufferProducer>& igbp) :
            mBqId{bqId}, mGeneration{generation}, mIgbp{igbp}, mNumAttached{0} {}
        BufferCache() : mBqId{0ULL}, mUsage{0ULL},
                mGeneration{0}, mIgbp{nullptr}, mNumAttached{0} {}
        BufferCache(uint64_t bqId, uint64_t usage, uint32_t generation,
                const sp<IGraphicBufferProducer>& igbp) :
            mBqId{bqId}, mUsage{usage}, mGeneration{generation}, mIgbp{igbp}, mNumAttached{0} {}

        ~BufferCache();

@@ -307,6 +310,10 @@ private:
    bool mStopRequested;
    std::atomic<int> mAllocAfterStopRequested;

    // Release Surface where we get allocations after stop/release being requested.
    class PlaceHolderSurface;
    std::unique_ptr<PlaceHolderSurface> mReleaseSurface;


private:
    explicit GraphicsTracker(int maxDequeueCount);