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

Commit 3d4039d7 authored by Brian Anderson's avatar Brian Anderson
Browse files

Use FenceTime to share fence times and reduce open fds.

FenceTimes are created and shared for each Fence that
FrameTimestampHistory and FrameTracker care about.

On the consumer side, the FenceTimes are also added to
shared timelines that are owned by SurfaceFlinger or
unshared timelines owned by Layer.  The timelines are
checked at the end of every frame to minimize the number
of file descriptors open.

On the producer side, the FenceTimes are added to
the ConsumerFrameEventHistory instead, since the timelines
that would be tracked by SurfaceFlinger are not shared
with anyone else in the consumer's process. The timelines
are checked just after a frame is queued to minimize
the number of file descriptors open.

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

Change-Id: Ifd4301affe1b24705b2bee7608c5a2c09dfb4041
parent 13e4db23
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@
#include <EGL/egl.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglext.h>


#include <ui/FenceTime.h>
#include <ui/Rect.h>
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/Region.h>


@@ -59,6 +60,9 @@ class BufferItem : public Flattenable<BufferItem> {
    // mFence is a fence that will signal when the buffer is idle.
    // mFence is a fence that will signal when the buffer is idle.
    sp<Fence> mFence;
    sp<Fence> mFence;


    // The std::shared_ptr<FenceTime> wrapper around mFence.
    std::shared_ptr<FenceTime> mFenceTime{FenceTime::NO_FENCE};

    // mCrop is the current crop rectangle for this buffer slot.
    // mCrop is the current crop rectangle for this buffer slot.
    Rect mCrop;
    Rect mCrop;


+57 −28
Original line number Original line Diff line number Diff line
@@ -17,7 +17,7 @@
#ifndef ANDROID_GUI_FRAMETIMESTAMPS_H
#ifndef ANDROID_GUI_FRAMETIMESTAMPS_H
#define ANDROID_GUI_FRAMETIMESTAMPS_H
#define ANDROID_GUI_FRAMETIMESTAMPS_H


#include <ui/Fence.h>
#include <ui/FenceTime.h>
#include <utils/Flattenable.h>
#include <utils/Flattenable.h>
#include <utils/StrongPointer.h>
#include <utils/StrongPointer.h>
#include <utils/Timers.h>
#include <utils/Timers.h>
@@ -28,12 +28,12 @@


namespace android {
namespace android {



struct FrameEvents;
struct FrameEvents;
class FrameEventHistoryDelta;
class FrameEventHistoryDelta;
class String8;
class String8;




// Identifiers for all the events that may be recorded or reported.
enum class FrameEvent {
enum class FrameEvent {
    POSTED,
    POSTED,
    REQUESTED_PRESENT,
    REQUESTED_PRESENT,
@@ -79,23 +79,17 @@ struct FrameEvents {
    bool addRetireCalled{false};
    bool addRetireCalled{false};
    bool addReleaseCalled{false};
    bool addReleaseCalled{false};


    nsecs_t postedTime{0};
    nsecs_t postedTime{-1};
    nsecs_t requestedPresentTime{0};
    nsecs_t requestedPresentTime{-1};
    nsecs_t latchTime{0};
    nsecs_t latchTime{-1};
    nsecs_t firstRefreshStartTime{0};
    nsecs_t firstRefreshStartTime{-1};
    nsecs_t lastRefreshStartTime{0};
    nsecs_t lastRefreshStartTime{-1};


    nsecs_t acquireTime{0};
    std::shared_ptr<FenceTime> acquireFence{FenceTime::NO_FENCE};
    nsecs_t gpuCompositionDoneTime{0};
    std::shared_ptr<FenceTime> gpuCompositionDoneFence{FenceTime::NO_FENCE};
    nsecs_t displayPresentTime{0};
    std::shared_ptr<FenceTime> displayPresentFence{FenceTime::NO_FENCE};
    nsecs_t displayRetireTime{0};
    std::shared_ptr<FenceTime> displayRetireFence{FenceTime::NO_FENCE};
    nsecs_t releaseTime{0};
    std::shared_ptr<FenceTime> releaseFence{FenceTime::NO_FENCE};

    sp<Fence> acquireFence{Fence::NO_FENCE};
    sp<Fence> gpuCompositionDoneFence{Fence::NO_FENCE};
    sp<Fence> displayPresentFence{Fence::NO_FENCE};
    sp<Fence> displayRetireFence{Fence::NO_FENCE};
    sp<Fence> releaseFence{Fence::NO_FENCE};
};
};




@@ -122,11 +116,23 @@ class ProducerFrameEventHistory : public FrameEventHistory {
public:
public:
    ~ProducerFrameEventHistory() override;
    ~ProducerFrameEventHistory() override;


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


    void updateSignalTimes();

private:
private:
    size_t mAcquireOffset{0};
    size_t mAcquireOffset{0};

    // The consumer updates it's timelines in Layer and SurfaceFlinger since
    // they can coordinate shared timelines better. The producer doesn't have
    // shared timelines though, so just let it own and update all of them.
    FenceTimeline mAcquireTimeline;
    FenceTimeline mGpuCompositionDoneTimeline;
    FenceTimeline mPresentTimeline;
    FenceTimeline mRetireTimeline;
    FenceTimeline mReleaseTimeline;
};
};




@@ -136,7 +142,7 @@ struct NewFrameEventsEntry {
    uint64_t frameNumber{0};
    uint64_t frameNumber{0};
    nsecs_t postedTime{0};
    nsecs_t postedTime{0};
    nsecs_t requestedPresentTime{0};
    nsecs_t requestedPresentTime{0};
    sp<Fence> acquireFence{Fence::NO_FENCE};
    std::shared_ptr<FenceTime> acquireFence{FenceTime::NO_FENCE};
};
};




@@ -175,13 +181,19 @@ public:
    void addLatch(uint64_t frameNumber, nsecs_t latchTime);
    void addLatch(uint64_t frameNumber, nsecs_t latchTime);
    void addPreComposition(uint64_t frameNumber, nsecs_t refreshStartTime);
    void addPreComposition(uint64_t frameNumber, nsecs_t refreshStartTime);
    void addPostComposition(uint64_t frameNumber,
    void addPostComposition(uint64_t frameNumber,
            sp<Fence> gpuCompositionDone, sp<Fence> displayPresent);
            const std::shared_ptr<FenceTime>& gpuCompositionDone,
    void addRetire(uint64_t frameNumber, sp<Fence> displayRetire);
            const std::shared_ptr<FenceTime>& displayPresent);
    void addRelease(uint64_t frameNumber, sp<Fence> release);
    void addRetire(uint64_t frameNumber,
            const std::shared_ptr<FenceTime>& displayRetire);
    void addRelease(uint64_t frameNumber,
            std::shared_ptr<FenceTime>&& release);


    void getAndResetDelta(FrameEventHistoryDelta* delta);
    void getAndResetDelta(FrameEventHistoryDelta* delta);


private:
private:
    void getFrameDelta(FrameEventHistoryDelta* delta,
            const std::array<FrameEvents, MAX_FRAME_HISTORY>::iterator& frame);

    std::array<FrameEventDirtyFields, MAX_FRAME_HISTORY> mFramesDirty;
    std::array<FrameEventDirtyFields, MAX_FRAME_HISTORY> mFramesDirty;
    size_t mQueueOffset{0};
    size_t mQueueOffset{0};
    size_t mCompositionOffset{0};
    size_t mCompositionOffset{0};
@@ -202,6 +214,13 @@ public:
            const FrameEvents& frameTimestamps,
            const FrameEvents& frameTimestamps,
            const FrameEventDirtyFields& dirtyFields);
            const FrameEventDirtyFields& dirtyFields);


    // Movable.
    FrameEventsDelta(FrameEventsDelta&& src) = default;
    FrameEventsDelta& operator=(FrameEventsDelta&& src) = default;
    // Not copyable.
    FrameEventsDelta(const FrameEventsDelta& src) = delete;
    FrameEventsDelta& operator=(const FrameEventsDelta& src) = delete;

    // Flattenable implementation
    // Flattenable implementation
    size_t getFlattenedSize() const;
    size_t getFlattenedSize() const;
    size_t getFdCount() const;
    size_t getFdCount() const;
@@ -226,10 +245,10 @@ private:
    nsecs_t mFirstRefreshStartTime{0};
    nsecs_t mFirstRefreshStartTime{0};
    nsecs_t mLastRefreshStartTime{0};
    nsecs_t mLastRefreshStartTime{0};


    sp<Fence> mGpuCompositionDoneFence{Fence::NO_FENCE};
    FenceTime::Snapshot mGpuCompositionDoneFence;
    sp<Fence> mDisplayPresentFence{Fence::NO_FENCE};
    FenceTime::Snapshot mDisplayPresentFence;
    sp<Fence> mDisplayRetireFence{Fence::NO_FENCE};
    FenceTime::Snapshot mDisplayRetireFence;
    sp<Fence> mReleaseFence{Fence::NO_FENCE};
    FenceTime::Snapshot mReleaseFence;


    // This is a static method with an auto return value so we can call
    // This is a static method with an auto return value so we can call
    // it without needing const and non-const versions.
    // it without needing const and non-const versions.
@@ -253,6 +272,16 @@ friend class ConsumerFrameEventHistory;
friend class ProducerFrameEventHistory;
friend class ProducerFrameEventHistory;


public:
public:
    FrameEventHistoryDelta() = default;

    // Movable.
    FrameEventHistoryDelta(FrameEventHistoryDelta&& src) = default;
    FrameEventHistoryDelta& operator=(FrameEventHistoryDelta&& src);
    // Not copyable.
    FrameEventHistoryDelta(const FrameEventHistoryDelta& src) = delete;
    FrameEventHistoryDelta& operator=(
            const FrameEventHistoryDelta& src) = delete;

    // Flattenable implementation.
    // Flattenable implementation.
    size_t getFlattenedSize() const;
    size_t getFlattenedSize() const;
    size_t getFdCount() const;
    size_t getFdCount() const;
+7 −0
Original line number Original line Diff line number Diff line
@@ -187,6 +187,10 @@ public:
    // ready to be read from.
    // ready to be read from.
    sp<Fence> getCurrentFence() const;
    sp<Fence> getCurrentFence() const;


    // getCurrentFence returns the FenceTime indicating when the current
    // buffer is ready to be read from.
    std::shared_ptr<FenceTime> getCurrentFenceTime() const;

    // doGLFenceWait inserts a wait command into the OpenGL ES command stream
    // doGLFenceWait inserts a wait command into the OpenGL ES command stream
    // to ensure that it is safe for future OpenGL ES commands to access the
    // to ensure that it is safe for future OpenGL ES commands to access the
    // current texture buffer.
    // current texture buffer.
@@ -398,6 +402,9 @@ private:
    // mCurrentFence is the fence received from BufferQueue in updateTexImage.
    // mCurrentFence is the fence received from BufferQueue in updateTexImage.
    sp<Fence> mCurrentFence;
    sp<Fence> mCurrentFence;


    // The FenceTime wrapper around mCurrentFence.
    std::shared_ptr<FenceTime> mCurrentFenceTime{FenceTime::NO_FENCE};

    // mCurrentTransformMatrix is the transform matrix for the current texture.
    // mCurrentTransformMatrix is the transform matrix for the current texture.
    // It gets computed by computeTransformMatrix each time updateTexImage is
    // It gets computed by computeTransformMatrix each time updateTexImage is
    // called.
    // called.
+9 −0
Original line number Original line Diff line number Diff line
@@ -363,6 +363,15 @@ public:
    };
    };


    struct QueueBufferOutput : public Flattenable<QueueBufferOutput> {
    struct QueueBufferOutput : public Flattenable<QueueBufferOutput> {
        QueueBufferOutput() = default;

        // Moveable.
        QueueBufferOutput(QueueBufferOutput&& src) = default;
        QueueBufferOutput& operator=(QueueBufferOutput&& src) = default;
        // Not copyable.
        QueueBufferOutput(const QueueBufferOutput& src) = delete;
        QueueBufferOutput& operator=(const QueueBufferOutput& src) = delete;

        // Flattenable protocol
        // Flattenable protocol
        static constexpr size_t minFlattenedSize();
        static constexpr size_t minFlattenedSize();
        size_t getFlattenedSize() const;
        size_t getFlattenedSize() const;
+2 −0
Original line number Original line Diff line number Diff line
@@ -204,6 +204,8 @@ status_t BufferItem::unflatten(
        status_t err = mFence->unflatten(buffer, size, fds, count);
        status_t err = mFence->unflatten(buffer, size, fds, count);
        if (err) return err;
        if (err) return err;
        size -= FlattenableUtils::align<4>(buffer);
        size -= FlattenableUtils::align<4>(buffer);

        mFenceTime = std::make_shared<FenceTime>(mFence);
    }
    }


    status_t err = mSurfaceDamage.unflatten(buffer, size);
    status_t err = mSurfaceDamage.unflatten(buffer, size);
Loading