From f7fd56a649f07133ad78d31eb5d3ae7a4e95d522 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 2 Sep 2016 10:10:04 -0700 Subject: [PATCH] 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 --- include/gui/Surface.h | 5 +- libs/gui/Surface.cpp | 47 ++++-- libs/gui/tests/Surface_test.cpp | 167 ++++++++++++---------- opengl/include/EGL/eglext.h | 13 +- opengl/libs/EGL/eglApi.cpp | 33 +++-- opengl/specs/EGL_ANDROID_get_frame_timestamps.txt | 41 ++++-- opengl/specs/README | 15 +- services/surfaceflinger/SurfaceFlinger.cpp | 3 + services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 3 + 9 files changed, 210 insertions(+), 117 deletions(-) diff --git a/include/gui/Surface.h b/include/gui/Surface.h index 43b8d965d2..0b6a8f763f 100644 --- a/include/gui/Surface.h +++ b/include/gui/Surface.h @@ -146,9 +146,10 @@ public: // 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 ead8ecb3b4..c8598287cc 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -150,27 +150,39 @@ void Surface::enableFrameTimestamps(bool enable) { 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 @@ static void getFrameTimestampFence(nsecs_t *dst, const std::shared_ptrgetFrameTimestamps(&delta); mFrameEventHistory->applyDelta(delta); @@ -232,7 +246,10 @@ status_t Surface::getFrameTimestamps(uint64_t frameNumber, } 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 @@ int Surface::dispatchGetFrameTimestamps(va_list args) { 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 858a2d3080..e40b4eb075 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -357,8 +357,11 @@ public: *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 @@ protected: 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 @@ protected: // that's okay for the purposes of this test. std::shared_ptr 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 @@ protected: 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 @@ protected: 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 @@ TEST_F(GetFrameTimestampsTest, DefaultDisabled) { // 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 @@ TEST_F(GetFrameTimestampsTest, EnabledSimple) { // 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 @@ TEST_F(GetFrameTimestampsTest, TimestampsAssociatedWithCorrectFrame) { // 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 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { 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 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { 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 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { 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 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { 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 @@ TEST_F(GetFrameTimestampsTest, ZeroRequestedTimestampsNoSync) { 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 @@ TEST_F(GetFrameTimestampsTest, FencesInProducerNoSync) { 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 @@ TEST_F(GetFrameTimestampsTest, FencesInProducerNoSync) { 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 @@ TEST_F(GetFrameTimestampsTest, FencesInProducerNoSync) { 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 @@ TEST_F(GetFrameTimestampsTest, NoGpuNoSync) { // 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 @@ TEST_F(GetFrameTimestampsTest, NoGpuNoSync) { // 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 @@ TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) { 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 @@ TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) { 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 @@ void GetFrameTimestampsTest::PresentOrRetireUnsupportedNoSyncTest( 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 874e712ae2..8b754d5fbb 100644 --- a/opengl/include/EGL/eglext.h +++ b/opengl/include/EGL/eglext.h @@ -634,11 +634,14 @@ typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLCREATENATIVECLIENTBUFFERANDROID) (co #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 3af7e935e3..388905c90e 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -2041,10 +2041,13 @@ EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, 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 @@ EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, 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 @@ EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, 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 @@ EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, } 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 @@ EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, #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 b5b6eb575b..7aa0d30481 100644 --- a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt +++ b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt @@ -69,11 +69,14 @@ New Tokens 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 @@ Changes to Chapter 3 of the EGL 1.5 Specification (EGL Functions and Errors) 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 @@ Revision History #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 1ee99fb164..8a3a7aa947 100644 --- a/opengl/specs/README +++ b/opengl/specs/README @@ -22,9 +22,12 @@ for use by Android extensions. 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 23c4b303a6..ff8db161b4 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -575,10 +575,13 @@ status_t SurfaceFlinger::getSupportedFrameTimestamps( *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 5c4245055a..92ecdbe4dc 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -607,9 +607,12 @@ status_t SurfaceFlinger::getSupportedFrameTimestamps( *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; -- 2.11.0