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

Commit 49670c84 authored by Brian C. Anderson's avatar Brian C. Anderson Committed by Android (Google) Code Review
Browse files

Merge "Cache frame event history producer-side."

parents 2da7a448 3890c399
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -66,9 +66,9 @@ public:
        virtual void onFrameReplaced(const BufferItem& item) override;
        virtual void onBuffersReleased() override;
        virtual void onSidebandStreamChanged() override;
        virtual bool addAndGetFrameTimestamps(
        virtual void addAndGetFrameTimestamps(
                const NewFrameEventsEntry* newTimestamps,
                uint64_t frameNumber, FrameTimestamps* outTimestamps) override;
                FrameEventHistoryDelta* outDelta) override;
    private:
        // mConsumerListener is a weak reference to the IConsumerListener.  This is
        // the raison d'etre of ProxyConsumerListener.
+3 −5
Original line number Diff line number Diff line
@@ -177,8 +177,7 @@ public:
            sp<Fence>* outFence, float outTransformMatrix[16]) override;

    // See IGraphicBufferProducer::getFrameTimestamps
    virtual bool getFrameTimestamps(uint64_t frameNumber,
            FrameTimestamps* outTimestamps) override;
    virtual void getFrameTimestamps(FrameEventHistoryDelta* outDelta) override;

    // See IGraphicBufferProducer::getUniqueId
    virtual status_t getUniqueId(uint64_t* outId) const override;
@@ -195,9 +194,8 @@ private:
    // BufferQueueCore::INVALID_BUFFER_SLOT otherwise
    int getFreeSlotLocked() const;

    bool addAndGetFrameTimestamps(
            const NewFrameEventsEntry* newTimestamps,
            uint64_t frameNumber, FrameTimestamps* outTimestamps);
    void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
            FrameEventHistoryDelta* outDelta);

    // waitForFreeSlotThenRelock finds the oldest slot in the FREE state. It may
    // block if there are no available slots and we are not in non-blocking
+176 −31
Original line number Diff line number Diff line
@@ -23,47 +23,52 @@
#include <utils/Timers.h>

#include <array>
#include <bitset>
#include <vector>

namespace android {


struct FrameEvents;
class FrameEventHistoryDelta;
class String8;


enum class SupportableFrameTimestamps {
enum class FrameEvent {
    POSTED,
    REQUESTED_PRESENT,
    LATCH,
    ACQUIRE,
    REFRESH_START,
    GL_COMPOSITION_DONE_TIME,
    DISPLAY_PRESENT_TIME,
    DISPLAY_RETIRE_TIME,
    RELEASE_TIME,
};


// The timestamps the consumer sends to the producer over binder.
struct FrameTimestamps : public LightFlattenablePod<FrameTimestamps> {
    FrameTimestamps() = default;
    explicit FrameTimestamps(const FrameEvents& fences);

    uint64_t frameNumber{0};
    nsecs_t postedTime{0};
    nsecs_t requestedPresentTime{0};
    nsecs_t acquireTime{0};
    nsecs_t refreshStartTime{0};
    nsecs_t glCompositionDoneTime{0};
    nsecs_t displayPresentTime{0};
    nsecs_t displayRetireTime{0};
    nsecs_t releaseTime{0};
    FIRST_REFRESH_START,
    LAST_REFRESH_START,
    GL_COMPOSITION_DONE,
    DISPLAY_PRESENT,
    DISPLAY_RETIRE,
    RELEASE,
    EVENT_COUNT, // Not an actual event.
};


// A collection of timestamps corresponding to a single frame.
struct FrameEvents {
    bool hasPostedInfo() const;
    bool hasRequestedPresentInfo() const;
    bool hasLatchInfo() const;
    bool hasFirstRefreshStartInfo() const;
    bool hasLastRefreshStartInfo() const;
    bool hasAcquireInfo() const;
    bool hasGpuCompositionDoneInfo() const;
    bool hasDisplayPresentInfo() const;
    bool hasDisplayRetireInfo() const;
    bool hasReleaseInfo() const;

    void checkFencesForCompletion();
    void dump(String8& outString) const;

    static constexpr size_t EVENT_COUNT =
            static_cast<size_t>(FrameEvent::EVENT_COUNT);
    static_assert(EVENT_COUNT <= 32, "Event count sanity check failed.");

    bool valid{false};
    uint64_t frameNumber{0};

@@ -72,6 +77,7 @@ struct FrameEvents {
    // a) we'll just never get them or b) they're not ready yet.
    bool addPostCompositeCalled{false};
    bool addRetireCalled{false};
    bool addReleaseCalled{false};

    nsecs_t postedTime{0};
    nsecs_t requestedPresentTime{0};
@@ -93,6 +99,39 @@ struct FrameEvents {
};


// A short history of frames that are synchronized between the consumer and
// producer via deltas.
class FrameEventHistory {
public:
    virtual ~FrameEventHistory();

    FrameEvents* getFrame(uint64_t frameNumber);
    FrameEvents* getFrame(uint64_t frameNumber, size_t* iHint);
    void checkFencesForCompletion();
    void dump(String8& outString) const;

    static constexpr size_t MAX_FRAME_HISTORY = 8;

protected:
    std::array<FrameEvents, MAX_FRAME_HISTORY> mFrames;
};


// The producer's interface to FrameEventHistory
class ProducerFrameEventHistory : public FrameEventHistory {
public:
    ~ProducerFrameEventHistory() override;

    void updateAcquireFence(uint64_t frameNumber, sp<Fence> acquire);
    void applyDelta(const FrameEventHistoryDelta& delta);

private:
    size_t mAcquireOffset{0};
};


// Used by the consumer to create a new frame event record that is
// partially complete.
struct NewFrameEventsEntry {
    uint64_t frameNumber{0};
    nsecs_t postedTime{0};
@@ -101,14 +140,38 @@ struct NewFrameEventsEntry {
};


class FrameEventHistory {
// Used by the consumer to keep track of which fields it already sent to
// the producer.
class FrameEventDirtyFields {
public:
    FrameEvents* getFrame(uint64_t frameNumber);
    FrameEvents* getFrame(uint64_t frameNumber, size_t* iHint);
    void checkFencesForCompletion();
    void dump(String8& outString) const;
    inline void reset() { mBitset.reset(); }
    inline bool anyDirty() const { return mBitset.any(); }

    template <FrameEvent event>
    inline void setDirty() {
        constexpr size_t eventIndex = static_cast<size_t>(event);
        static_assert(eventIndex < FrameEvents::EVENT_COUNT, "Bad index.");
        mBitset.set(eventIndex);
    }

    template <FrameEvent event>
    inline bool isDirty() const {
        constexpr size_t eventIndex = static_cast<size_t>(event);
        static_assert(eventIndex < FrameEvents::EVENT_COUNT, "Bad index.");
        return mBitset[eventIndex];
    }

private:
    std::bitset<FrameEvents::EVENT_COUNT> mBitset;
};


    void addQueue(const NewFrameEventsEntry& newFrameEntry);
// The consumer's interface to FrameEventHistory
class ConsumerFrameEventHistory : public FrameEventHistory {
public:
    ~ConsumerFrameEventHistory() override;

    void addQueue(const NewFrameEventsEntry& newEntry);
    void addLatch(uint64_t frameNumber, nsecs_t latchTime);
    void addPreComposition(uint64_t frameNumber, nsecs_t refreshStartTime);
    void addPostComposition(uint64_t frameNumber,
@@ -116,14 +179,96 @@ public:
    void addRetire(uint64_t frameNumber, sp<Fence> displayRetire);
    void addRelease(uint64_t frameNumber, sp<Fence> release);

    void getAndResetDelta(FrameEventHistoryDelta* delta);

private:
    static constexpr size_t MAX_FRAME_HISTORY = 8;
    std::array<FrameEvents, MAX_FRAME_HISTORY> mFrames;
    std::array<FrameEventDirtyFields, MAX_FRAME_HISTORY> mFramesDirty;
    size_t mQueueOffset{0};
    size_t mCompositionOffset{0};
    size_t mRetireOffset{0};
    size_t mReleaseOffset{0};
};


// A single frame update from the consumer to producer that can be sent
// through Binder.
// Although this may be sent multiple times for the same frame as new
// timestamps are set, Fences only need to be sent once.
class FrameEventsDelta : public Flattenable<FrameEventsDelta> {
friend class ProducerFrameEventHistory;
public:
    FrameEventsDelta() = default;
    FrameEventsDelta(size_t index,
            const FrameEvents& frameTimestamps,
            const FrameEventDirtyFields& dirtyFields);

    // Flattenable implementation
    size_t getFlattenedSize() const;
    size_t getFdCount() const;
    status_t flatten(void*& buffer, size_t& size, int*& fds,
            size_t& count) const;
    status_t unflatten(void const*& buffer, size_t& size, int const*& fds,
            size_t& count);

private:
    static size_t minFlattenedSize();

    size_t mIndex{0};
    uint64_t mFrameNumber{0};

    bool mAddPostCompositeCalled{0};
    bool mAddRetireCalled{0};
    bool mAddReleaseCalled{0};

    nsecs_t mPostedTime{0};
    nsecs_t mRequestedPresentTime{0};
    nsecs_t mLatchTime{0};
    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};
    sp<Fence> mReleaseFence{Fence::NO_FENCE};

    // 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> {
        return {{
            &fed->mAcquireFence, &fed->mGpuCompositionDoneFence,
            &fed->mDisplayPresentFence, &fed->mDisplayRetireFence,
            &fed->mReleaseFence
        }};
    }
};


// A collection of updates from consumer to producer that can be sent
// through Binder.
class FrameEventHistoryDelta
        : public Flattenable<FrameEventHistoryDelta> {

friend class ConsumerFrameEventHistory;
friend class ProducerFrameEventHistory;

public:
    // Flattenable implementation.
    size_t getFlattenedSize() const;
    size_t getFdCount() const;
    status_t flatten(void*& buffer, size_t& size, int*& fds,
            size_t& count) const;
    status_t unflatten(void const*& buffer, size_t& size, int const*& fds,
            size_t& count);

private:
    static size_t minFlattenedSize();

    std::vector<FrameEventsDelta> mDeltas;
};


} // namespace android
#endif
+4 −6
Original line number Diff line number Diff line
@@ -82,13 +82,11 @@ public:
    // different stream.
    virtual void onSidebandStreamChanged() = 0; /* Asynchronous */

    // Notifies the consumer of any new producer-side events and then queries
    // the consumer timestamps
    virtual bool addAndGetFrameTimestamps(
    // Notifies the consumer of any new producer-side timestamps and
    // returns the combined frame history that hasn't already been retrieved.
    virtual void addAndGetFrameTimestamps(
            const NewFrameEventsEntry* /*newTimestamps*/,
            uint64_t /*frameNumber*/, FrameTimestamps* /*outTimestamps*/) {
        return false;
    }
            FrameEventHistoryDelta* /*outDelta*/) {}
};


+2 −7
Original line number Diff line number Diff line
@@ -588,13 +588,8 @@ public:
    virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
            sp<Fence>* outFence, float outTransformMatrix[16]) = 0;

    // Attempts to retrieve timestamp information for the given frame number.
    // If information for the given frame number is not found, returns false.
    // Returns true otherwise.
    //
    // If a fence has not yet signaled the timestamp returned will be 0;
    virtual bool getFrameTimestamps(uint64_t /*frameNumber*/,
            FrameTimestamps* /*outTimestamps*/) { return false; }
    // Gets the frame events that haven't already been retrieved.
    virtual void getFrameTimestamps(FrameEventHistoryDelta* /*outDelta*/) {}

    // Returns a unique id for this BufferQueue
    virtual status_t getUniqueId(uint64_t* outId) const = 0;
Loading