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
diff --git a/include/gui/BufferItem.h b/include/gui/BufferItem.h
index 5232d0f..ab676cc 100644
--- a/include/gui/BufferItem.h
+++ b/include/gui/BufferItem.h
@@ -20,6 +20,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
+#include <ui/FenceTime.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -59,6 +60,9 @@
// mFence is a fence that will signal when the buffer is idle.
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.
Rect mCrop;
diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h
index 0e95ec3..a1d4e07 100644
--- a/include/gui/FrameTimestamps.h
+++ b/include/gui/FrameTimestamps.h
@@ -17,7 +17,7 @@
#ifndef ANDROID_GUI_FRAMETIMESTAMPS_H
#define ANDROID_GUI_FRAMETIMESTAMPS_H
-#include <ui/Fence.h>
+#include <ui/FenceTime.h>
#include <utils/Flattenable.h>
#include <utils/StrongPointer.h>
#include <utils/Timers.h>
@@ -28,12 +28,12 @@
namespace android {
-
struct FrameEvents;
class FrameEventHistoryDelta;
class String8;
+// Identifiers for all the events that may be recorded or reported.
enum class FrameEvent {
POSTED,
REQUESTED_PRESENT,
@@ -79,23 +79,17 @@
bool addRetireCalled{false};
bool addReleaseCalled{false};
- nsecs_t postedTime{0};
- nsecs_t requestedPresentTime{0};
- nsecs_t latchTime{0};
- nsecs_t firstRefreshStartTime{0};
- nsecs_t lastRefreshStartTime{0};
+ nsecs_t postedTime{-1};
+ nsecs_t requestedPresentTime{-1};
+ nsecs_t latchTime{-1};
+ nsecs_t firstRefreshStartTime{-1};
+ nsecs_t lastRefreshStartTime{-1};
- nsecs_t acquireTime{0};
- nsecs_t gpuCompositionDoneTime{0};
- nsecs_t displayPresentTime{0};
- nsecs_t displayRetireTime{0};
- nsecs_t releaseTime{0};
-
- 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};
+ std::shared_ptr<FenceTime> acquireFence{FenceTime::NO_FENCE};
+ std::shared_ptr<FenceTime> gpuCompositionDoneFence{FenceTime::NO_FENCE};
+ std::shared_ptr<FenceTime> displayPresentFence{FenceTime::NO_FENCE};
+ std::shared_ptr<FenceTime> displayRetireFence{FenceTime::NO_FENCE};
+ std::shared_ptr<FenceTime> releaseFence{FenceTime::NO_FENCE};
};
@@ -122,11 +116,23 @@
public:
~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 updateSignalTimes();
+
private:
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 @@
uint64_t frameNumber{0};
nsecs_t postedTime{0};
nsecs_t requestedPresentTime{0};
- sp<Fence> acquireFence{Fence::NO_FENCE};
+ std::shared_ptr<FenceTime> acquireFence{FenceTime::NO_FENCE};
};
@@ -175,13 +181,19 @@
void addLatch(uint64_t frameNumber, nsecs_t latchTime);
void addPreComposition(uint64_t frameNumber, nsecs_t refreshStartTime);
void addPostComposition(uint64_t frameNumber,
- sp<Fence> gpuCompositionDone, sp<Fence> displayPresent);
- void addRetire(uint64_t frameNumber, sp<Fence> displayRetire);
- void addRelease(uint64_t frameNumber, sp<Fence> release);
+ const std::shared_ptr<FenceTime>& gpuCompositionDone,
+ const std::shared_ptr<FenceTime>& displayPresent);
+ 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);
private:
+ void getFrameDelta(FrameEventHistoryDelta* delta,
+ const std::array<FrameEvents, MAX_FRAME_HISTORY>::iterator& frame);
+
std::array<FrameEventDirtyFields, MAX_FRAME_HISTORY> mFramesDirty;
size_t mQueueOffset{0};
size_t mCompositionOffset{0};
@@ -202,6 +214,13 @@
const FrameEvents& frameTimestamps,
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
size_t getFlattenedSize() const;
size_t getFdCount() const;
@@ -226,10 +245,10 @@
nsecs_t mFirstRefreshStartTime{0};
nsecs_t mLastRefreshStartTime{0};
- sp<Fence> mGpuCompositionDoneFence{Fence::NO_FENCE};
- sp<Fence> mDisplayPresentFence{Fence::NO_FENCE};
- sp<Fence> mDisplayRetireFence{Fence::NO_FENCE};
- sp<Fence> mReleaseFence{Fence::NO_FENCE};
+ FenceTime::Snapshot mGpuCompositionDoneFence;
+ FenceTime::Snapshot mDisplayPresentFence;
+ FenceTime::Snapshot mDisplayRetireFence;
+ FenceTime::Snapshot mReleaseFence;
// This is a static method with an auto return value so we can call
// it without needing const and non-const versions.
@@ -253,6 +272,16 @@
friend class ProducerFrameEventHistory;
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.
size_t getFlattenedSize() const;
size_t getFdCount() const;
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index 6ff1303..493ecde 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -187,6 +187,10 @@
// ready to be read from.
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
// to ensure that it is safe for future OpenGL ES commands to access the
// current texture buffer.
@@ -398,6 +402,9 @@
// mCurrentFence is the fence received from BufferQueue in updateTexImage.
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.
// It gets computed by computeTransformMatrix each time updateTexImage is
// called.
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 492db35..304a0c0 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -363,6 +363,15 @@
};
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
static constexpr size_t minFlattenedSize();
size_t getFlattenedSize() const;