EGL: Expose latch, last composite, and dequeue ready.
Also fix discontinuous reserved token values.
Test: adb shell /data/nativetest/libgui_test/libgui_test
--gtest_filter=*GetFrameTimestamps*
Change-Id: I9d513b8784a7205dfe534c1c74b56c18cd49e74a
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 43b8d96..0b6a8f7 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -146,9 +146,10 @@
// See IGraphicBufferProducer::getFrameTimestamps
status_t getFrameTimestamps(uint64_t frameNumber,
nsecs_t* outRequestedPresentTime, nsecs_t* outAcquireTime,
- nsecs_t* outRefreshStartTime, nsecs_t* outGlCompositionDoneTime,
+ nsecs_t* outLatchTime, nsecs_t* outFirstRefreshStartTime,
+ nsecs_t* outLastRefreshStartTime, nsecs_t* outGlCompositionDoneTime,
nsecs_t* outDisplayPresentTime, nsecs_t* outDisplayRetireTime,
- nsecs_t* outReleaseTime);
+ nsecs_t* outDequeueReadyTime, nsecs_t* outReleaseTime);
status_t getUniqueId(uint64_t* outId) const;
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index ead8ecb..c859828 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -150,27 +150,39 @@
static bool checkConsumerForUpdates(
const FrameEvents* e, const uint64_t lastFrameNumber,
- const nsecs_t* outRefreshStartTime,
+ const nsecs_t* outLatchTime,
+ const nsecs_t* outFirstRefreshStartTime,
+ const nsecs_t* outLastRefreshStartTime,
const nsecs_t* outGlCompositionDoneTime,
const nsecs_t* outDisplayPresentTime,
const nsecs_t* outDisplayRetireTime,
+ const nsecs_t* outDequeueReadyTime,
const nsecs_t* outReleaseTime) {
- bool checkForRefreshStart = (outRefreshStartTime != nullptr) &&
+ bool checkForLatch = (outLatchTime != nullptr) && !e->hasLatchInfo();
+ bool checkForFirstRefreshStart = (outFirstRefreshStartTime != nullptr) &&
!e->hasFirstRefreshStartInfo();
bool checkForGlCompositionDone = (outGlCompositionDoneTime != nullptr) &&
!e->hasGpuCompositionDoneInfo();
bool checkForDisplayPresent = (outDisplayPresentTime != nullptr) &&
!e->hasDisplayPresentInfo();
- // DisplayRetire and Release are never available for the last frame.
+ // LastRefreshStart, DisplayRetire, DequeueReady, and Release are never
+ // available for the last frame.
+ bool checkForLastRefreshStart = (outLastRefreshStartTime != nullptr) &&
+ !e->hasLastRefreshStartInfo() &&
+ (e->frameNumber != lastFrameNumber);
bool checkForDisplayRetire = (outDisplayRetireTime != nullptr) &&
!e->hasDisplayRetireInfo() && (e->frameNumber != lastFrameNumber);
+ bool checkForDequeueReady = (outDequeueReadyTime != nullptr) &&
+ !e->hasDequeueReadyInfo() && (e->frameNumber != lastFrameNumber);
bool checkForRelease = (outReleaseTime != nullptr) &&
!e->hasReleaseInfo() && (e->frameNumber != lastFrameNumber);
// RequestedPresent and Acquire info are always available producer-side.
- return checkForRefreshStart || checkForGlCompositionDone ||
- checkForDisplayPresent || checkForDisplayRetire || checkForRelease;
+ return checkForLatch || checkForFirstRefreshStart ||
+ checkForLastRefreshStart || checkForGlCompositionDone ||
+ checkForDisplayPresent || checkForDisplayRetire ||
+ checkForDequeueReady || checkForRelease;
}
static void getFrameTimestamp(nsecs_t *dst, const nsecs_t& src) {
@@ -188,9 +200,10 @@
status_t Surface::getFrameTimestamps(uint64_t frameNumber,
nsecs_t* outRequestedPresentTime, nsecs_t* outAcquireTime,
- nsecs_t* outRefreshStartTime, nsecs_t* outGlCompositionDoneTime,
+ nsecs_t* outLatchTime, nsecs_t* outFirstRefreshStartTime,
+ nsecs_t* outLastRefreshStartTime, nsecs_t* outGlCompositionDoneTime,
nsecs_t* outDisplayPresentTime, nsecs_t* outDisplayRetireTime,
- nsecs_t* outReleaseTime) {
+ nsecs_t* outDequeueReadyTime, nsecs_t* outReleaseTime) {
ATRACE_CALL();
Mutex::Autolock lock(mMutex);
@@ -217,8 +230,9 @@
// Update our cache of events if the requested events are not available.
if (checkConsumerForUpdates(events, mLastFrameNumber,
- outRefreshStartTime, outGlCompositionDoneTime,
- outDisplayPresentTime, outDisplayRetireTime, outReleaseTime)) {
+ outLatchTime, outFirstRefreshStartTime, outLastRefreshStartTime,
+ outGlCompositionDoneTime, outDisplayPresentTime,
+ outDisplayRetireTime, outDequeueReadyTime, outReleaseTime)) {
FrameEventHistoryDelta delta;
mGraphicBufferProducer->getFrameTimestamps(&delta);
mFrameEventHistory->applyDelta(delta);
@@ -232,7 +246,10 @@
}
getFrameTimestamp(outRequestedPresentTime, events->requestedPresentTime);
- getFrameTimestamp(outRefreshStartTime, events->firstRefreshStartTime);
+ getFrameTimestamp(outLatchTime, events->latchTime);
+ getFrameTimestamp(outFirstRefreshStartTime, events->firstRefreshStartTime);
+ getFrameTimestamp(outLastRefreshStartTime, events->lastRefreshStartTime);
+ getFrameTimestamp(outDequeueReadyTime, events->dequeueReadyTime);
getFrameTimestampFence(outAcquireTime, events->acquireFence);
getFrameTimestampFence(
@@ -941,15 +958,19 @@
uint32_t framesAgo = va_arg(args, uint32_t);
nsecs_t* outRequestedPresentTime = va_arg(args, int64_t*);
nsecs_t* outAcquireTime = va_arg(args, int64_t*);
- nsecs_t* outRefreshStartTime = va_arg(args, int64_t*);
+ nsecs_t* outLatchTime = va_arg(args, int64_t*);
+ nsecs_t* outFirstRefreshStartTime = va_arg(args, int64_t*);
+ nsecs_t* outLastRefreshStartTime = va_arg(args, int64_t*);
nsecs_t* outGlCompositionDoneTime = va_arg(args, int64_t*);
nsecs_t* outDisplayPresentTime = va_arg(args, int64_t*);
nsecs_t* outDisplayRetireTime = va_arg(args, int64_t*);
+ nsecs_t* outDequeueReadyTime = va_arg(args, int64_t*);
nsecs_t* outReleaseTime = va_arg(args, int64_t*);
return getFrameTimestamps(getNextFrameNumber() - 1 - framesAgo,
- outRequestedPresentTime, outAcquireTime, outRefreshStartTime,
+ outRequestedPresentTime, outAcquireTime, outLatchTime,
+ outFirstRefreshStartTime, outLastRefreshStartTime,
outGlCompositionDoneTime, outDisplayPresentTime,
- outDisplayRetireTime, outReleaseTime);
+ outDisplayRetireTime, outDequeueReadyTime, outReleaseTime);
}
int Surface::connect(int api) {
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 858a2d3..e40b4eb 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -357,8 +357,11 @@
*outSupported = {
FrameEvent::REQUESTED_PRESENT,
FrameEvent::ACQUIRE,
+ FrameEvent::LATCH,
FrameEvent::FIRST_REFRESH_START,
+ FrameEvent::LAST_REFRESH_START,
FrameEvent::GL_COMPOSITION_DONE,
+ FrameEvent::DEQUEUE_READY,
FrameEvent::RELEASE
};
if (mSupportsPresent) {
@@ -591,13 +594,24 @@
mFrameTimestampsEnabled = true;
}
+ int getAllFrameTimestamps(uint32_t framesAgo) {
+ return native_window_get_frame_timestamps(mWindow.get(), framesAgo,
+ &outRequestedPresentTime, &outAcquireTime, &outLatchTime,
+ &outFirstRefreshStartTime, &outLastRefreshStartTime,
+ &outGpuCompositionDoneTime, &outDisplayPresentTime,
+ &outDisplayRetireTime, &outDequeueReadyTime, &outReleaseTime);
+ }
+
void resetTimestamps() {
outRequestedPresentTime = -1;
outAcquireTime = -1;
- outRefreshStartTime = -1;
+ outLatchTime = -1;
+ outFirstRefreshStartTime = -1;
+ outLastRefreshStartTime = -1;
outGpuCompositionDoneTime = -1;
outDisplayPresentTime = -1;
outDisplayRetireTime = -1;
+ outDequeueReadyTime = -1;
outReleaseTime = -1;
}
@@ -647,6 +661,19 @@
// that's okay for the purposes of this test.
std::shared_ptr<FenceTime> gpuDoneFenceTime = FenceTime::NO_FENCE;
+ // Composite the previous frame one more time, which helps verify
+ // LastRefresh is updated properly.
+ if (oldFrame != nullptr) {
+ mCfeh->addPreComposition(nOldFrame,
+ oldFrame->mRefreshes[2].kStartTime);
+ gpuDoneFenceTime = gpuComposited ?
+ oldFrame->mRefreshes[2].mGpuCompositionDone.mFenceTime :
+ FenceTime::NO_FENCE;
+ mCfeh->addPostComposition(nOldFrame, gpuDoneFenceTime,
+ oldFrame->mRefreshes[2].mPresent.mFenceTime);
+ }
+
+ // Latch the new frame.
mCfeh->addLatch(nNewFrame, newFrame->kLatchTime);
mCfeh->addPreComposition(nNewFrame, newFrame->mRefreshes[0].kStartTime);
@@ -673,12 +700,6 @@
FenceTime::NO_FENCE;
mCfeh->addPostComposition(nNewFrame, gpuDoneFenceTime,
newFrame->mRefreshes[1].mPresent.mFenceTime);
- mCfeh->addPreComposition(nNewFrame, newFrame->mRefreshes[2].kStartTime);
- gpuDoneFenceTime = gpuComposited ?
- newFrame->mRefreshes[2].mGpuCompositionDone.mFenceTime :
- FenceTime::NO_FENCE;
- mCfeh->addPostComposition(nNewFrame, gpuDoneFenceTime,
- newFrame->mRefreshes[2].mPresent.mFenceTime);
}
void QueryPresentRetireSupported(
@@ -699,10 +720,13 @@
int64_t outRequestedPresentTime = -1;
int64_t outAcquireTime = -1;
- int64_t outRefreshStartTime = -1;
+ int64_t outLatchTime = -1;
+ int64_t outFirstRefreshStartTime = -1;
+ int64_t outLastRefreshStartTime = -1;
int64_t outGpuCompositionDoneTime = -1;
int64_t outDisplayPresentTime = -1;
int64_t outDisplayRetireTime = -1;
+ int64_t outDequeueReadyTime = -1;
int64_t outReleaseTime = -1;
FrameEvents mFrames[2] { { mFenceMap, 1000 }, { mFenceMap, 2000 } };
@@ -734,10 +758,7 @@
// Verify attempts to get frame timestamps fail.
const uint32_t framesAgo = 0;
- int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
- &outRequestedPresentTime, &outAcquireTime, &outRefreshStartTime,
- &outGpuCompositionDoneTime, &outDisplayPresentTime,
- &outDisplayRetireTime, &outReleaseTime);
+ int result = getAllFrameTimestamps(framesAgo);
EXPECT_EQ(INVALID_OPERATION, result);
EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount);
}
@@ -778,10 +799,7 @@
// Verify queries for timestamps that the producer doesn't know about
// triggers a call to see if the consumer has any new timestamps.
const uint32_t framesAgo = 0;
- int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
- &outRequestedPresentTime, &outAcquireTime, &outRefreshStartTime,
- &outGpuCompositionDoneTime, &outDisplayPresentTime,
- &outDisplayRetireTime, &outReleaseTime);
+ int result = getAllFrameTimestamps(framesAgo);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(3, mFakeConsumer->mGetFrameTimestampsCount);
}
@@ -833,35 +851,35 @@
// Verify timestamps are correct for frame 1.
uint32_t framesAgo = 1;
resetTimestamps();
- int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
- &outRequestedPresentTime, &outAcquireTime, &outRefreshStartTime,
- &outGpuCompositionDoneTime, &outDisplayPresentTime,
- &outDisplayRetireTime, &outReleaseTime);
+ int result = getAllFrameTimestamps(framesAgo);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
- EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outRefreshStartTime);
+ EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kGpuCompositionDoneTime,
outGpuCompositionDoneTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kPresentTime, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kRetireTime, outDisplayRetireTime);
+ EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
EXPECT_EQ(mFrames[0].kReleaseTime, outReleaseTime);
// Verify timestamps are correct for frame 2.
framesAgo = 0;
resetTimestamps();
- result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
- &outRequestedPresentTime, &outAcquireTime, &outRefreshStartTime,
- &outGpuCompositionDoneTime, &outDisplayPresentTime,
- &outDisplayRetireTime, &outReleaseTime);
+ result = getAllFrameTimestamps(framesAgo);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime);
EXPECT_EQ(mFrames[1].kProducerAcquireTime, outAcquireTime);
- EXPECT_EQ(mFrames[1].mRefreshes[0].kStartTime, outRefreshStartTime);
+ EXPECT_EQ(mFrames[1].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[1].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[1].mRefreshes[1].kStartTime, outLastRefreshStartTime);
EXPECT_EQ(mFrames[1].mRefreshes[0].kGpuCompositionDoneTime,
outGpuCompositionDoneTime);
EXPECT_EQ(mFrames[1].mRefreshes[0].kPresentTime, outDisplayPresentTime);
EXPECT_EQ(0, outDisplayRetireTime);
+ EXPECT_EQ(0, outDequeueReadyTime);
EXPECT_EQ(0, outReleaseTime);
}
@@ -883,7 +901,7 @@
int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
&outRequestedPresentTime, &outAcquireTime, nullptr, nullptr,
- nullptr, nullptr, nullptr);
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
@@ -895,7 +913,7 @@
oldCount = mFakeConsumer->mGetFrameTimestampsCount;
result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
&outRequestedPresentTime, &outAcquireTime, nullptr, nullptr,
- nullptr, nullptr, nullptr);
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
@@ -911,7 +929,7 @@
oldCount = mFakeConsumer->mGetFrameTimestampsCount;
result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
&outRequestedPresentTime, &outAcquireTime, nullptr, nullptr,
- nullptr, nullptr, nullptr);
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime);
@@ -923,7 +941,7 @@
oldCount = mFakeConsumer->mGetFrameTimestampsCount;
result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
&outRequestedPresentTime, &outAcquireTime, nullptr, nullptr,
- nullptr, nullptr, nullptr);
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime);
@@ -952,7 +970,9 @@
const uint32_t framesAgo = 0;
int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr);
+ EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
}
@@ -980,18 +1000,18 @@
uint32_t framesAgo = 1;
resetTimestamps();
int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
- int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
- &outRequestedPresentTime, &outAcquireTime, &outRefreshStartTime,
- &outGpuCompositionDoneTime, &outDisplayPresentTime,
- &outDisplayRetireTime, &outReleaseTime);
+ int result = getAllFrameTimestamps(framesAgo);
EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
- EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outRefreshStartTime);
+ EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
EXPECT_EQ(0, outGpuCompositionDoneTime);
EXPECT_EQ(0, outDisplayPresentTime);
EXPECT_EQ(0, outDisplayRetireTime);
+ EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
EXPECT_EQ(0, outReleaseTime);
// Verify available timestamps are correct for frame 1 again, before any
@@ -1000,18 +1020,18 @@
framesAgo = 1;
resetTimestamps();
oldCount = mFakeConsumer->mGetFrameTimestampsCount;
- result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
- &outRequestedPresentTime, &outAcquireTime, &outRefreshStartTime,
- &outGpuCompositionDoneTime, &outDisplayPresentTime,
- &outDisplayRetireTime, &outReleaseTime);
+ result = getAllFrameTimestamps(framesAgo);
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
- EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outRefreshStartTime);
+ EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
EXPECT_EQ(0, outGpuCompositionDoneTime);
EXPECT_EQ(0, outDisplayPresentTime);
EXPECT_EQ(0, outDisplayRetireTime);
+ EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
EXPECT_EQ(0, outReleaseTime);
// Signal the fences for frame 1.
@@ -1022,19 +1042,19 @@
framesAgo = 1;
resetTimestamps();
oldCount = mFakeConsumer->mGetFrameTimestampsCount;
- result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
- &outRequestedPresentTime, &outAcquireTime, &outRefreshStartTime,
- &outGpuCompositionDoneTime, &outDisplayPresentTime,
- &outDisplayRetireTime, &outReleaseTime);
+ result = getAllFrameTimestamps(framesAgo);
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
- EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outRefreshStartTime);
+ EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kGpuCompositionDoneTime,
outGpuCompositionDoneTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kPresentTime, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kRetireTime, outDisplayRetireTime);
+ EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
EXPECT_EQ(mFrames[0].kReleaseTime, outReleaseTime);
}
@@ -1064,18 +1084,18 @@
// addFrameEvents didn't get to piggyback on the earlier queues/dequeues.
resetTimestamps();
int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
- int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
- &outRequestedPresentTime, &outAcquireTime, &outRefreshStartTime,
- &outGpuCompositionDoneTime, &outDisplayPresentTime,
- &outDisplayRetireTime, &outReleaseTime);
+ int result = getAllFrameTimestamps(framesAgo);
EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
- EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outRefreshStartTime);
+ EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
EXPECT_EQ(0, outGpuCompositionDoneTime);
EXPECT_EQ(0, outDisplayPresentTime);
EXPECT_EQ(0, outDisplayRetireTime);
+ EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
EXPECT_EQ(0, outReleaseTime);
// Signal the fences for frame 1.
@@ -1086,23 +1106,23 @@
// sync call.
resetTimestamps();
oldCount = mFakeConsumer->mGetFrameTimestampsCount;
- result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
- &outRequestedPresentTime, &outAcquireTime, &outRefreshStartTime,
- &outGpuCompositionDoneTime, &outDisplayPresentTime,
- &outDisplayRetireTime, &outReleaseTime);
+ result = getAllFrameTimestamps(framesAgo);
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
- EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outRefreshStartTime);
+ EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
EXPECT_EQ(0, outGpuCompositionDoneTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kPresentTime, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kRetireTime, outDisplayRetireTime);
+ EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
EXPECT_EQ(mFrames[0].kReleaseTime, outReleaseTime);
}
-// This test verifies that if the retire/release info can't possibly exist,
-// a sync call is not done.
+// This test verifies that if the certain timestamps can't possibly exist for
+// the most recent frame, then a sync call is not done.
TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) {
enableFrameTimestamps();
mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true);
@@ -1125,18 +1145,18 @@
uint32_t framesAgo = 1;
resetTimestamps();
int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
- int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
- &outRequestedPresentTime, &outAcquireTime, &outRefreshStartTime,
- &outGpuCompositionDoneTime, &outDisplayPresentTime,
- &outDisplayRetireTime, &outReleaseTime);
+ int result = getAllFrameTimestamps(framesAgo);
EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
- EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outRefreshStartTime);
+ EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
EXPECT_EQ(0, outGpuCompositionDoneTime);
EXPECT_EQ(0, outDisplayPresentTime);
EXPECT_EQ(0, outDisplayRetireTime);
+ EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
EXPECT_EQ(0, outReleaseTime);
mFrames[0].signalRefreshFences();
@@ -1144,24 +1164,25 @@
mFrames[1].signalRefreshFences();
// Verify querying for all timestmaps of f2 does not do a sync call.
- // Even though the retire and release times aren't available, a sync call
- // should not occur because it's not possible for it to be retired or
- // released until another frame is queued.
+ // Even though the lastRefresh, retire, dequeueReady, and release times aren't
+ // available, a sync call should not occur because it's not possible for f2
+ // to encounter the final value for those events until another frame is
+ // queued.
framesAgo = 0;
resetTimestamps();
oldCount = mFakeConsumer->mGetFrameTimestampsCount;
- result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
- &outRequestedPresentTime, &outAcquireTime, &outRefreshStartTime,
- &outGpuCompositionDoneTime, &outDisplayPresentTime,
- &outDisplayRetireTime, &outReleaseTime);
+ result = getAllFrameTimestamps(framesAgo);
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime);
EXPECT_EQ(mFrames[1].kProducerAcquireTime, outAcquireTime);
- EXPECT_EQ(mFrames[1].mRefreshes[0].kStartTime, outRefreshStartTime);
+ EXPECT_EQ(mFrames[1].kLatchTime, outLatchTime);
+ EXPECT_EQ(mFrames[1].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
+ EXPECT_EQ(mFrames[1].mRefreshes[1].kStartTime, outLastRefreshStartTime);
EXPECT_EQ(0, outGpuCompositionDoneTime);
EXPECT_EQ(mFrames[1].mRefreshes[0].kPresentTime, outDisplayPresentTime);
EXPECT_EQ(0, outDisplayRetireTime);
+ EXPECT_EQ(0, outDequeueReadyTime);
EXPECT_EQ(0, outReleaseTime);
}
@@ -1183,10 +1204,10 @@
resetTimestamps();
int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
- nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
displayPresentSupported ? nullptr : &outDisplayPresentTime,
displayRetireSupported ? nullptr : &outDisplayRetireTime,
- nullptr);
+ nullptr, nullptr);
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(BAD_VALUE, result);
EXPECT_EQ(-1, outDisplayRetireTime);
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 874e712..8b754d5 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -634,11 +634,14 @@
#define EGL_TIMESTAMPS_ANDROID 0x314D
#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x314E
#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x314F
-#define EGL_COMPOSITION_START_TIME_ANDROID 0x3430
-#define EGL_COMPOSITION_FINISHED_TIME_ANDROID 0x3431
-#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3432
-#define EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3433
-#define EGL_READS_DONE_TIME_ANDROID 0x3434
+#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3150
+#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3151
+#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3152
+#define EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID 0x3153
+#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3154
+#define EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3155
+#define EGL_DEQUEUE_READY_TIME_ANDROID 0x3156
+#define EGL_READS_DONE_TIME_ANDROID 0x3157
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
EGLAPI EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 3af7e93..388905c 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -2041,10 +2041,13 @@
nsecs_t* requestedPresentTime = nullptr;
nsecs_t* acquireTime = nullptr;
- nsecs_t* refreshStartTime = nullptr;
+ nsecs_t* latchTime = nullptr;
+ nsecs_t* firstRefreshStartTime = nullptr;
nsecs_t* GLCompositionDoneTime = nullptr;
+ nsecs_t* lastRefreshStartTime = nullptr;
nsecs_t* displayPresentTime = nullptr;
nsecs_t* displayRetireTime = nullptr;
+ nsecs_t* dequeueReadyTime = nullptr;
nsecs_t* releaseTime = nullptr;
for (int i = 0; i < numTimestamps; i++) {
@@ -2055,10 +2058,16 @@
case EGL_RENDERING_COMPLETE_TIME_ANDROID:
acquireTime = &values[i];
break;
- case EGL_COMPOSITION_START_TIME_ANDROID:
- refreshStartTime = &values[i];
+ case EGL_COMPOSITION_LATCH_TIME_ANDROID:
+ latchTime = &values[i];
break;
- case EGL_COMPOSITION_FINISHED_TIME_ANDROID:
+ case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
+ firstRefreshStartTime = &values[i];
+ break;
+ case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
+ lastRefreshStartTime = &values[i];
+ break;
+ case EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID:
GLCompositionDoneTime = &values[i];
break;
case EGL_DISPLAY_PRESENT_TIME_ANDROID:
@@ -2067,6 +2076,9 @@
case EGL_DISPLAY_RETIRE_TIME_ANDROID:
displayRetireTime = &values[i];
break;
+ case EGL_DEQUEUE_READY_TIME_ANDROID:
+ dequeueReadyTime = &values[i];
+ break;
case EGL_READS_DONE_TIME_ANDROID:
releaseTime = &values[i];
break;
@@ -2076,9 +2088,9 @@
}
status_t ret = native_window_get_frame_timestamps(s->win.get(), framesAgo,
- requestedPresentTime, acquireTime, refreshStartTime,
- GLCompositionDoneTime, displayPresentTime, displayRetireTime,
- releaseTime);
+ requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime,
+ lastRefreshStartTime, GLCompositionDoneTime, displayPresentTime,
+ displayRetireTime, dequeueReadyTime, releaseTime);
switch (ret) {
case NO_ERROR:
@@ -2122,8 +2134,11 @@
#if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS
case EGL_REQUESTED_PRESENT_TIME_ANDROID:
case EGL_RENDERING_COMPLETE_TIME_ANDROID:
- case EGL_COMPOSITION_START_TIME_ANDROID:
- case EGL_COMPOSITION_FINISHED_TIME_ANDROID:
+ case EGL_COMPOSITION_LATCH_TIME_ANDROID:
+ case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
+ case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
+ case EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID:
+ case EGL_DEQUEUE_READY_TIME_ANDROID:
case EGL_READS_DONE_TIME_ANDROID:
return EGL_TRUE;
case EGL_DISPLAY_PRESENT_TIME_ANDROID: {
diff --git a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
index b5b6eb5..7aa0d30 100644
--- a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
+++ b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
@@ -69,11 +69,14 @@
EGL_TIMESTAMPS_ANDROID 0x314D
EGL_REQUESTED_PRESENT_TIME_ANDROID 0x314E
EGL_RENDERING_COMPLETE_TIME_ANDROID 0x314F
- EGL_COMPOSITION_START_TIME_ANDROID 0x3430
- EGL_COMPOSITION_FINISHED_TIME_ANDROID 0x3431
- EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3432
- EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3433
- EGL_READS_DONE_TIME_ANDROID 0x3434
+ EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3150
+ EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3151
+ EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3152
+ EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID 0x3153
+ EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3154
+ EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3155
+ EGL_DEQUEUE_READY_TIME_ANDROID 0x3156
+ EGL_READS_DONE_TIME_ANDROID 0x3157
Add to the list of supported tokens for eglSurfaceAttrib in section 3.5.6
"Surface Attributes", page 43:
@@ -119,16 +122,31 @@
this will correspond to buffer's queue time.
- EGL_RENDERING_COMPLETE_TIME_ANDROID - The time when all of the
application's rendering to the surface was completed.
- - EGL_COMPOSITION_START_TIME_ANDROID - The time at which the compositor
- began preparing composition for this frame.
- - EGL_COMPOSITION_FINISHED_TIME_ANDROID - The time at which the
+ - EGL_COMPOSITION_LATCH_TIME_ANDROID - The time when the compositor
+ selected this frame as the one to use for the next composition. The
+ latch is the earliest indication that the frame was submitted in time
+ to be composited.
+ - EGL_FIRST_COMPOSITION_START_TIME_ANDROID - The first time at which
+ the compositor began preparing composition for this frame.
+ - EGL_LAST_COMPOSITION_START_TIME_ANDROID - The last time at which the
+ compositor began preparing composition for this frame. If this frame
+ is composited only once, it will have the same value as
+ EGL_FIRST_COMPOSITION_START_TIME_ANDROID. If the value is not equal,
+ that indicates the subsequent frame was not submitted in time to be
+ latched by the compositor. Note: The value may not be updated for
+ every display refresh if the compositor becomes idle.
+ - EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID - The time at which the
compositor's rendering work for this frame finished. This will be zero
if composition was handled by the display and the compositor didn't do
any rendering.
- EGL_DISPLAY_PRESENT_TIME_ANDROID - The time at which this frame
- started to scan out on the physical display.
+ started to scan out to the physical display.
- EGL_DISPLAY_RETIRE_TIME_ANDROID - The time at which this frame was
replaced by the next frame on-screen.
+ - EGL_DEQUEUE_READY_TIME_ANDROID - The time when the buffer became
+ available for reuse as a buffer the client can target without
+ blocking. This is generally the point when all read commands of the
+ buffer have been submitted, but not necessarily completed.
- EGL_READS_DONE_TIME_ANDROID - The time at which all reads for the
purpose of display/composition were completed for this frame.
@@ -152,3 +170,8 @@
#2 (Brian Anderson, July 22, 2016)
- Replace EGL_QUEUE_TIME_ANDROID with EGL_REQUESTED_PRESENT_TIME_ANDROID.
- Add DISPLAY_PRESENT_TIME_ANDROID.
+
+#3 (Brian Anderson, November 30, 2016)
+ - Add EGL_COMPOSITION_LATCH_TIME_ANDROID,
+ EGL_LAST_COMPOSITION_START_TIME_ANDROID, and
+ EGL_DEQUEUE_READY_TIME_ANDROID.
diff --git a/opengl/specs/README b/opengl/specs/README
index 1ee99fb..8a3a7aa 100644
--- a/opengl/specs/README
+++ b/opengl/specs/README
@@ -22,9 +22,12 @@
0x314D EGL_TIMESTAMPS_ANDROID (EGL_ANDROID_get_frame_timestamps)
0x314E EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
0x314F EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3430 EGL_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3431 EGL_COMPOSITION_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3432 EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3433 EGL_DISPLAY_RETIRE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3434 EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3435 - 0x343F (unused)
+0x3150 EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3151 EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3152 EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3153 EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3154 EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3155 EGL_DISPLAY_RETIRE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3156 EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3157 EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3158 - 0x315F (unused)
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 23c4b30..ff8db16 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -575,10 +575,13 @@
*outSupported = {
FrameEvent::REQUESTED_PRESENT,
FrameEvent::ACQUIRE,
+ FrameEvent::LATCH,
FrameEvent::FIRST_REFRESH_START,
+ FrameEvent::LAST_REFRESH_START,
FrameEvent::GL_COMPOSITION_DONE,
getHwComposer().presentFenceRepresentsStartOfScanout() ?
FrameEvent::DISPLAY_PRESENT : FrameEvent::DISPLAY_RETIRE,
+ FrameEvent::DEQUEUE_READY,
FrameEvent::RELEASE,
};
return NO_ERROR;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 5c42450..92ecdbe 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -607,9 +607,12 @@
*outSupported = {
FrameEvent::REQUESTED_PRESENT,
FrameEvent::ACQUIRE,
+ FrameEvent::LATCH,
FrameEvent::FIRST_REFRESH_START,
+ FrameEvent::LAST_REFRESH_START,
FrameEvent::GL_COMPOSITION_DONE,
FrameEvent::DISPLAY_RETIRE,
+ FrameEvent::DEQUEUE_READY,
FrameEvent::RELEASE,
};
return NO_ERROR;