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

Commit 7c3ba8aa authored by Brian Anderson's avatar Brian Anderson
Browse files

Update producer's cache of frame events in de/queue

* Cache is only updated during queue and dequeue if
    the getFrameTimestamps is enabled.
* The consumer avoids sending a copy of the acquire
    fence back to the producer since the producer
    already has a copy.

Test: adb shell /data/nativetest/libgui_test/libgui_test
--gtest_filter=*GetFrameTimestamps*

Change-Id: I6a8b965ae79441a40893b5df937f9ed004fe7359
parent 3890c399
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -80,9 +80,9 @@ public:
    //
    // In both cases, the producer will need to call requestBuffer to get a
    // GraphicBuffer handle for the returned slot.
    virtual status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence,
    status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence,
            uint32_t width, uint32_t height, PixelFormat format,
            uint32_t usage);
            uint32_t usage, FrameEventHistoryDelta* outTimestamps) override;

    // See IGraphicBufferProducer::detachBuffer
    virtual status_t detachBuffer(int slot);
+5 −7
Original line number Diff line number Diff line
@@ -226,7 +226,6 @@ private:
    nsecs_t mFirstRefreshStartTime{0};
    nsecs_t mLastRefreshStartTime{0};

    sp<Fence> mAcquireFence{Fence::NO_FENCE};
    sp<Fence> mGpuCompositionDoneFence{Fence::NO_FENCE};
    sp<Fence> mDisplayPresentFence{Fence::NO_FENCE};
    sp<Fence> mDisplayRetireFence{Fence::NO_FENCE};
@@ -234,13 +233,12 @@ private:

    // This is a static method with an auto return value so we can call
    // it without needing const and non-const versions.
    template <typename ThisType>
    static inline auto allFences(ThisType fed) ->
            std::array<decltype(&fed->mAcquireFence), 5> {
    template <typename ThisT>
    static inline auto allFences(ThisT fed) ->
            std::array<decltype(&fed->mReleaseFence), 4> {
        return {{
            &fed->mAcquireFence, &fed->mGpuCompositionDoneFence,
            &fed->mDisplayPresentFence, &fed->mDisplayRetireFence,
            &fed->mReleaseFence
            &fed->mGpuCompositionDoneFence, &fed->mDisplayPresentFence,
            &fed->mDisplayRetireFence, &fed->mReleaseFence
        }};
    }
};
+15 −31
Original line number Diff line number Diff line
@@ -190,7 +190,8 @@ public:
    // All other negative values are an unknown error returned downstream
    // from the graphics allocator (typically errno).
    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
            uint32_t h, PixelFormat format, uint32_t usage) = 0;
            uint32_t h, PixelFormat format, uint32_t usage,
            FrameEventHistoryDelta* outTimestamps) = 0;

    // detachBuffer attempts to remove all ownership of the buffer in the given
    // slot from the buffer queue. If this call succeeds, the slot will be
@@ -306,20 +307,23 @@ public:
        //         set this to Fence::NO_FENCE if the buffer is ready immediately
        // sticky - the sticky transform set in Surface (only used by the LEGACY
        //          camera mode).
        // getFrameTimestamps - whether or not the latest frame timestamps
        //                      should be retrieved from the consumer.
        inline QueueBufferInput(int64_t _timestamp, bool _isAutoTimestamp,
                android_dataspace _dataSpace, const Rect& _crop,
                int _scalingMode, uint32_t _transform, const sp<Fence>& _fence,
                uint32_t _sticky = 0)
                uint32_t _sticky = 0, bool _getFrameTimestamps = false)
                : timestamp(_timestamp), isAutoTimestamp(_isAutoTimestamp),
                  dataSpace(_dataSpace), crop(_crop), scalingMode(_scalingMode),
                  transform(_transform), stickyTransform(_sticky), fence(_fence),
                  surfaceDamage() { }
                  surfaceDamage(), getFrameTimestamps(_getFrameTimestamps) { }

        inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp,
                android_dataspace* outDataSpace,
                Rect* outCrop, int* outScalingMode,
                uint32_t* outTransform, sp<Fence>* outFence,
                uint32_t* outStickyTransform = nullptr) const {
                uint32_t* outStickyTransform = nullptr,
                bool* outGetFrameTimestamps = nullptr) const {
            *outTimestamp = timestamp;
            *outIsAutoTimestamp = bool(isAutoTimestamp);
            *outDataSpace = dataSpace;
@@ -330,9 +334,13 @@ public:
            if (outStickyTransform != NULL) {
                *outStickyTransform = stickyTransform;
            }
            if (outGetFrameTimestamps) {
                *outGetFrameTimestamps = getFrameTimestamps;
            }
        }

        // Flattenable protocol
        static constexpr size_t minFlattenedSize();
        size_t getFlattenedSize() const;
        size_t getFdCount() const;
        status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
@@ -351,37 +359,12 @@ public:
        uint32_t stickyTransform{0};
        sp<Fence> fence;
        Region surfaceDamage;
        bool getFrameTimestamps{false};
    };

    struct QueueBufferOutput : public Flattenable<QueueBufferOutput> {
        // outWidth - filled with default width applied to the buffer
        // outHeight - filled with default height applied to the buffer
        // outTransformHint - filled with default transform applied to the buffer
        // outNumPendingBuffers - num buffers queued that haven't yet been acquired
        //                        (counting the currently queued buffer)
        inline void deflate(uint32_t* outWidth,
                uint32_t* outHeight,
                uint32_t* outTransformHint,
                uint32_t* outNumPendingBuffers,
                uint64_t* outNextFrameNumber) const {
            *outWidth = width;
            *outHeight = height;
            *outTransformHint = transformHint;
            *outNumPendingBuffers = numPendingBuffers;
            *outNextFrameNumber = nextFrameNumber;
        }

        inline void inflate(uint32_t inWidth, uint32_t inHeight,
                uint32_t inTransformHint, uint32_t inNumPendingBuffers,
                uint64_t inNextFrameNumber) {
            width = inWidth;
            height = inHeight;
            transformHint = inTransformHint;
            numPendingBuffers = inNumPendingBuffers;
            nextFrameNumber = inNextFrameNumber;
        }

        // Flattenable protocol
        static constexpr size_t minFlattenedSize();
        size_t getFlattenedSize() const;
        size_t getFdCount() const;
        status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
@@ -392,6 +375,7 @@ public:
        uint32_t transformHint{0};
        uint32_t numPendingBuffers{0};
        uint64_t nextFrameNumber{0};
        FrameEventHistoryDelta frameTimestamps;
    };

    virtual status_t queueBuffer(int slot, const QueueBufferInput& input,
+8 −0
Original line number Diff line number Diff line
@@ -134,6 +134,12 @@ public:
    status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
            sp<Fence>* outFence, float outTransformMatrix[16]);

    /* Enables or disables frame timestamp tracking. It is disabled by default
     * to avoid overhead during queue and dequeue for applications that don't
     * need the feature. If disabled, calls to getFrameTimestamps will fail.
     */
    void enableFrameTimestamps(bool enable);

    // See IGraphicBufferProducer::getFrameTimestamps
    status_t getFrameTimestamps(uint64_t frameNumber,
            nsecs_t* outRequestedPresentTime, nsecs_t* outAcquireTime,
@@ -192,6 +198,7 @@ private:
    int dispatchSetSurfaceDamage(va_list args);
    int dispatchSetSharedBufferMode(va_list args);
    int dispatchSetAutoRefresh(va_list args);
    int dispatchEnableFrameTimestamps(va_list args);
    int dispatchGetFrameTimestamps(va_list args);

protected:
@@ -390,6 +397,7 @@ private:
    mutable bool mFrameTimestampsSupportsRetire;

    // A cached copy of the FrameEventHistory maintained by the consumer.
    bool mEnableFrameTimestamps = false;
    ProducerFrameEventHistory mFrameEventHistory;
};

+21 −11
Original line number Diff line number Diff line
@@ -348,7 +348,8 @@ status_t BufferQueueProducer::waitForFreeSlotThenRelock(FreeSlotCaller caller,

status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
        sp<android::Fence> *outFence, uint32_t width, uint32_t height,
        PixelFormat format, uint32_t usage) {
        PixelFormat format, uint32_t usage,
        FrameEventHistoryDelta* outTimestamps) {
    ATRACE_CALL();
    { // Autolock scope
        Mutex::Autolock lock(mCore->mMutex);
@@ -560,6 +561,8 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
            mSlots[*outSlot].mFrameNumber,
            mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);

    addAndGetFrameTimestamps(nullptr, outTimestamps);

    return returnFlags;
}

@@ -748,8 +751,10 @@ status_t BufferQueueProducer::queueBuffer(int slot,
    uint32_t transform;
    uint32_t stickyTransform;
    sp<Fence> acquireFence;
    bool getFrameTimestamps = false;
    input.deflate(&requestedPresentTimestamp, &isAutoTimestamp, &dataSpace,
            &crop, &scalingMode, &transform, &acquireFence, &stickyTransform);
            &crop, &scalingMode, &transform, &acquireFence, &stickyTransform,
            &getFrameTimestamps);
    Region surfaceDamage = input.getSurfaceDamage();

    if (acquireFence == NULL) {
@@ -913,10 +918,11 @@ status_t BufferQueueProducer::queueBuffer(int slot,
        mCore->mDequeueCondition.broadcast();
        mCore->mLastQueuedSlot = slot;

        output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
                mCore->mTransformHint,
                static_cast<uint32_t>(mCore->mQueue.size()),
                mCore->mFrameCounter + 1);
        output->width = mCore->mDefaultWidth;
        output->height = mCore->mDefaultHeight;
        output->transformHint = mCore->mTransformHint;
        output->numPendingBuffers = static_cast<uint32_t>(mCore->mQueue.size());
        output->nextFrameNumber = mCore->mFrameCounter + 1;

        ATRACE_INT(mCore->mConsumerName.string(),
                static_cast<int32_t>(mCore->mQueue.size()));
@@ -975,7 +981,8 @@ status_t BufferQueueProducer::queueBuffer(int slot,
        requestedPresentTimestamp,
        acquireFence
    };
    addAndGetFrameTimestamps(&newFrameEventsEntry, nullptr);
    addAndGetFrameTimestamps(&newFrameEventsEntry,
            getFrameTimestamps ? &output->frameTimestamps : nullptr);

    return NO_ERROR;
}
@@ -1141,10 +1148,13 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
        case NATIVE_WINDOW_API_MEDIA:
        case NATIVE_WINDOW_API_CAMERA:
            mCore->mConnectedApi = api;
            output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
                    mCore->mTransformHint,
                    static_cast<uint32_t>(mCore->mQueue.size()),
                    mCore->mFrameCounter + 1);

            output->width = mCore->mDefaultWidth;
            output->height = mCore->mDefaultHeight;
            output->transformHint = mCore->mTransformHint;
            output->numPendingBuffers =
                    static_cast<uint32_t>(mCore->mQueue.size());
            output->nextFrameNumber = mCore->mFrameCounter + 1;

            if (listener != NULL) {
                // Set up a death notification so that we can disconnect
Loading