Loading include/gui/Surface.h +1 −0 Original line number Diff line number Diff line Loading @@ -204,6 +204,7 @@ private: int dispatchSetSurfaceDamage(va_list args); int dispatchSetSharedBufferMode(va_list args); int dispatchSetAutoRefresh(va_list args); int dispatchGetNextFrameId(va_list args); int dispatchEnableFrameTimestamps(va_list args); int dispatchGetFrameTimestamps(va_list args); int dispatchGetDisplayRefreshCycleDuration(va_list args); Loading libs/gui/Surface.cpp +11 −2 Original line number Diff line number Diff line Loading @@ -831,6 +831,9 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_SET_AUTO_REFRESH: res = dispatchSetAutoRefresh(args); break; case NATIVE_WINDOW_GET_NEXT_FRAME_ID: res = dispatchGetNextFrameId(args); break; case NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS: res = dispatchEnableFrameTimestamps(args); break; Loading Loading @@ -960,6 +963,12 @@ int Surface::dispatchSetAutoRefresh(va_list args) { return setAutoRefresh(autoRefresh); } int Surface::dispatchGetNextFrameId(va_list args) { uint64_t* nextFrameId = va_arg(args, uint64_t*); *nextFrameId = getNextFrameNumber(); return NO_ERROR; } int Surface::dispatchEnableFrameTimestamps(va_list args) { bool enable = va_arg(args, int); enableFrameTimestamps(enable); Loading @@ -967,7 +976,7 @@ int Surface::dispatchEnableFrameTimestamps(va_list args) { } int Surface::dispatchGetFrameTimestamps(va_list args) { uint32_t framesAgo = va_arg(args, uint32_t); uint64_t frameId = va_arg(args, uint64_t); nsecs_t* outRequestedPresentTime = va_arg(args, int64_t*); nsecs_t* outAcquireTime = va_arg(args, int64_t*); nsecs_t* outLatchTime = va_arg(args, int64_t*); Loading @@ -978,7 +987,7 @@ int Surface::dispatchGetFrameTimestamps(va_list args) { 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, return getFrameTimestamps(frameId, outRequestedPresentTime, outAcquireTime, outLatchTime, outFirstRefreshStartTime, outLastRefreshStartTime, outGlCompositionDoneTime, outDisplayPresentTime, Loading libs/gui/tests/Surface_test.cpp +45 −40 Original line number Diff line number Diff line Loading @@ -598,8 +598,8 @@ protected: mFrameTimestampsEnabled = true; } int getAllFrameTimestamps(uint32_t framesAgo) { return native_window_get_frame_timestamps(mWindow.get(), framesAgo, int getAllFrameTimestamps(uint64_t frameId) { return native_window_get_frame_timestamps(mWindow.get(), frameId, &outRequestedPresentTime, &outAcquireTime, &outLatchTime, &outFirstRefreshStartTime, &outLastRefreshStartTime, &outGpuCompositionDoneTime, &outDisplayPresentTime, Loading @@ -619,6 +619,13 @@ protected: outReleaseTime = -1; } uint64_t getNextFrameId() { uint64_t frameId = -1; int status = native_window_get_next_frame_id(mWindow.get(), &frameId); EXPECT_EQ(status, NO_ERROR); return frameId; } void dequeueAndQueue(uint64_t frameIndex) { int fence = -1; ANativeWindowBuffer* buffer = nullptr; Loading Loading @@ -748,6 +755,8 @@ TEST_F(GetFrameTimestampsTest, DefaultDisabled) { EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount); EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount); const uint64_t fId = getNextFrameId(); // Verify the producer doesn't get frame timestamps piggybacked on dequeue. ASSERT_EQ(NO_ERROR, mWindow->dequeueBuffer(mWindow.get(), &buffer, &fence)); EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount); Loading @@ -761,8 +770,7 @@ TEST_F(GetFrameTimestampsTest, DefaultDisabled) { EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount); // Verify attempts to get frame timestamps fail. const uint32_t framesAgo = 0; int result = getAllFrameTimestamps(framesAgo); int result = getAllFrameTimestamps(fId); EXPECT_EQ(INVALID_OPERATION, result); EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount); } Loading @@ -778,6 +786,8 @@ TEST_F(GetFrameTimestampsTest, EnabledSimple) { EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount); EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount); const uint64_t fId1 = getNextFrameId(); // Verify getFrameTimestamps is piggybacked on dequeue. ASSERT_EQ(NO_ERROR, mWindow->dequeueBuffer(mWindow.get(), &buffer, &fence)); EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount); Loading @@ -802,8 +812,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 = getAllFrameTimestamps(framesAgo); int result = getAllFrameTimestamps(fId1); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(3, mFakeConsumer->mGetFrameTimestampsCount); } Loading Loading @@ -833,16 +842,17 @@ TEST_F(GetFrameTimestampsTest, QueryRetireSupported) { QueryPresentRetireSupported(false, true); } // This test verifies that: // 1) The timestamps recorded in the consumer's FrameTimestampsHistory are // properly retrieved by the producer for the correct frames. // 2) When framesAgo is 0, it is querying for the most recently queued frame. // This verifies the timestamps recorded in the consumer's // FrameTimestampsHistory are properly retrieved by the producer for the // correct frames. TEST_F(GetFrameTimestampsTest, TimestampsAssociatedWithCorrectFrame) { enableFrameTimestamps(); const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); mFrames[0].signalQueueFences(); const uint64_t fId2 = getNextFrameId(); dequeueAndQueue(1); mFrames[1].signalQueueFences(); Loading @@ -853,9 +863,8 @@ TEST_F(GetFrameTimestampsTest, TimestampsAssociatedWithCorrectFrame) { mFrames[1].signalRefreshFences(); // Verify timestamps are correct for frame 1. uint32_t framesAgo = 1; resetTimestamps(); int result = getAllFrameTimestamps(framesAgo); int result = getAllFrameTimestamps(fId1); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime); Loading @@ -870,9 +879,8 @@ TEST_F(GetFrameTimestampsTest, TimestampsAssociatedWithCorrectFrame) { EXPECT_EQ(mFrames[0].kReleaseTime, outReleaseTime); // Verify timestamps are correct for frame 2. framesAgo = 0; resetTimestamps(); result = getAllFrameTimestamps(framesAgo); result = getAllFrameTimestamps(fId2); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime); EXPECT_EQ(mFrames[1].kProducerAcquireTime, outAcquireTime); Loading @@ -893,9 +901,8 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { enableFrameTimestamps(); mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true); const uint32_t framesAgo = 0; // Dequeue and queue frame 1. const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); // Verify queue-related timestamps for f1 are available immediately in the Loading @@ -903,7 +910,7 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { // acquire fence. resetTimestamps(); int oldCount = mFakeConsumer->mGetFrameTimestampsCount; int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, int result = native_window_get_frame_timestamps(mWindow.get(), fId1, &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); Loading @@ -915,7 +922,7 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { mFrames[0].signalQueueFences(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, result = native_window_get_frame_timestamps(mWindow.get(), fId1, &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); Loading @@ -924,6 +931,7 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime); // Dequeue and queue frame 2. const uint64_t fId2 = getNextFrameId(); dequeueAndQueue(1); // Verify queue-related timestamps for f2 are available immediately in the Loading @@ -931,7 +939,7 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { // acquire fence. resetTimestamps(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, result = native_window_get_frame_timestamps(mWindow.get(), fId2, &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); Loading @@ -943,7 +951,7 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { mFrames[1].signalQueueFences(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, result = native_window_get_frame_timestamps(mWindow.get(), fId2, &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); Loading @@ -961,6 +969,7 @@ TEST_F(GetFrameTimestampsTest, ZeroRequestedTimestampsNoSync) { mFrames[0].signalQueueFences(); // Dequeue and queue frame 2. const uint64_t fId2 = getNextFrameId(); dequeueAndQueue(1); mFrames[1].signalQueueFences(); Loading @@ -971,9 +980,8 @@ TEST_F(GetFrameTimestampsTest, ZeroRequestedTimestampsNoSync) { mFrames[1].signalRefreshFences(); // Verify a request for no timestamps doesn't result in a sync call. const uint32_t framesAgo = 0; int oldCount = mFakeConsumer->mGetFrameTimestampsCount; int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, int result = native_window_get_frame_timestamps(mWindow.get(), fId2, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(NO_ERROR, result); Loading @@ -987,6 +995,7 @@ TEST_F(GetFrameTimestampsTest, FencesInProducerNoSync) { mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true); // Dequeue and queue frame 1. const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); mFrames[0].signalQueueFences(); Loading @@ -1001,10 +1010,9 @@ TEST_F(GetFrameTimestampsTest, FencesInProducerNoSync) { // fence has been signaled. // Note: A sync call is necessary here since the events triggered by // addFrameEvents didn't get to piggyback on the earlier queues/dequeues. uint32_t framesAgo = 1; resetTimestamps(); int oldCount = mFakeConsumer->mGetFrameTimestampsCount; int result = getAllFrameTimestamps(framesAgo); int result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); Loading @@ -1021,10 +1029,9 @@ TEST_F(GetFrameTimestampsTest, FencesInProducerNoSync) { // Verify available timestamps are correct for frame 1 again, before any // fence has been signaled. // This time a sync call should not be necessary. framesAgo = 1; resetTimestamps(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; result = getAllFrameTimestamps(framesAgo); result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); Loading @@ -1043,10 +1050,9 @@ TEST_F(GetFrameTimestampsTest, FencesInProducerNoSync) { mFrames[0].signalReleaseFences(); // Verify all timestamps are available without a sync call. framesAgo = 1; resetTimestamps(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; result = getAllFrameTimestamps(framesAgo); result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); Loading @@ -1069,9 +1075,8 @@ TEST_F(GetFrameTimestampsTest, NoGpuNoSync) { enableFrameTimestamps(); mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true); const uint32_t framesAgo = 1; // Dequeue and queue frame 1. const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); mFrames[0].signalQueueFences(); Loading @@ -1088,7 +1093,7 @@ TEST_F(GetFrameTimestampsTest, NoGpuNoSync) { // addFrameEvents didn't get to piggyback on the earlier queues/dequeues. resetTimestamps(); int oldCount = mFakeConsumer->mGetFrameTimestampsCount; int result = getAllFrameTimestamps(framesAgo); int result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); Loading @@ -1110,7 +1115,7 @@ TEST_F(GetFrameTimestampsTest, NoGpuNoSync) { // sync call. resetTimestamps(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; result = getAllFrameTimestamps(framesAgo); result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); Loading @@ -1132,10 +1137,12 @@ TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) { mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true); // Dequeue and queue frame 1. const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); mFrames[0].signalQueueFences(); // Dequeue and queue frame 2. const uint64_t fId2 = getNextFrameId(); dequeueAndQueue(1); mFrames[1].signalQueueFences(); Loading @@ -1146,10 +1153,9 @@ TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) { // fence has been signaled. // Note: A sync call is necessary here since the events triggered by // addFrameEvents didn't get to piggyback on the earlier queues/dequeues. uint32_t framesAgo = 1; resetTimestamps(); int oldCount = mFakeConsumer->mGetFrameTimestampsCount; int result = getAllFrameTimestamps(framesAgo); int result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); Loading @@ -1167,15 +1173,14 @@ TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) { mFrames[0].signalReleaseFences(); mFrames[1].signalRefreshFences(); // Verify querying for all timestmaps of f2 does not do a sync call. // Even though the lastRefresh, retire, dequeueReady, and release times aren't // Verify querying for all timestmaps of f2 does not do a sync call. 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 = getAllFrameTimestamps(framesAgo); result = getAllFrameTimestamps(fId2); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime); Loading @@ -1200,14 +1205,14 @@ void GetFrameTimestampsTest::PresentOrRetireUnsupportedNoSyncTest( displayPresentSupported, displayRetireSupported); // Dequeue and queue frame 1. const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); // Verify a query for the Present and Retire times do not trigger // a sync call if they are not supported. const uint32_t framesAgo = 0; resetTimestamps(); int oldCount = mFakeConsumer->mGetFrameTimestampsCount; int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, int result = native_window_get_frame_timestamps(mWindow.get(), fId1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, displayPresentSupported ? nullptr : &outDisplayPresentTime, displayRetireSupported ? nullptr : &outDisplayRetireTime, Loading opengl/include/EGL/eglext.h +4 −2 Original line number Diff line number Diff line Loading @@ -643,10 +643,12 @@ typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLCREATENATIVECLIENTBUFFERANDROID) (co #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 eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId); EGLAPI EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values); EGLAPI EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint timestamp); #else typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values); typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETNEXTFRAMEIDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId); typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSANDROID) (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values); typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYTIMESTAMPSUPPORTEDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint timestamp); #endif #endif Loading opengl/libs/EGL/eglApi.cpp +39 −2 Original line number Diff line number Diff line Loading @@ -216,6 +216,8 @@ static const extention_map_t sExtensionMap[] = { (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR }, // EGL_ANDROID_get_frame_timestamps { "eglGetNextFrameIdANDROID", (__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID }, { "eglGetFrameTimestampsANDROID", (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID }, { "eglQueryTimestampSupportedANDROID", Loading Loading @@ -2048,8 +2050,42 @@ EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface, return EGL_FALSE; } EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId) { clearError(); const egl_display_ptr dp = validate_display(dpy); if (!dp) { return setError(EGL_BAD_DISPLAY, EGL_FALSE); } SurfaceRef _s(dp.get(), surface); if (!_s.get()) { return setError(EGL_BAD_SURFACE, EGL_FALSE); } egl_surface_t const * const s = get_surface(surface); if (!s->win.get()) { return setError(EGL_BAD_SURFACE, EGL_FALSE); } uint64_t nextFrameId = 0; status_t ret = native_window_get_next_frame_id(s->win.get(), &nextFrameId); if (ret != NO_ERROR) { // This should not happen. Return an error that is not in the spec // so it's obvious something is very wrong. ALOGE("eglGetNextFrameId: Unexpected error."); return setError(EGL_NOT_INITIALIZED, EGL_FALSE); } *frameId = nextFrameId; return EGL_TRUE; } EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values) { clearError(); Loading Loading @@ -2118,7 +2154,7 @@ EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, } } status_t ret = native_window_get_frame_timestamps(s->win.get(), framesAgo, status_t ret = native_window_get_frame_timestamps(s->win.get(), frameId, requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime, lastRefreshStartTime, GLCompositionDoneTime, displayPresentTime, displayRetireTime, dequeueReadyTime, releaseTime); Loading @@ -2135,6 +2171,7 @@ EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, default: // This should not happen. Return an error that is not in the spec // so it's obvious something is very wrong. ALOGE("eglGetFrameTimestamps: Unexpected error."); return setError(EGL_NOT_INITIALIZED, EGL_FALSE); } } Loading Loading
include/gui/Surface.h +1 −0 Original line number Diff line number Diff line Loading @@ -204,6 +204,7 @@ private: int dispatchSetSurfaceDamage(va_list args); int dispatchSetSharedBufferMode(va_list args); int dispatchSetAutoRefresh(va_list args); int dispatchGetNextFrameId(va_list args); int dispatchEnableFrameTimestamps(va_list args); int dispatchGetFrameTimestamps(va_list args); int dispatchGetDisplayRefreshCycleDuration(va_list args); Loading
libs/gui/Surface.cpp +11 −2 Original line number Diff line number Diff line Loading @@ -831,6 +831,9 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_SET_AUTO_REFRESH: res = dispatchSetAutoRefresh(args); break; case NATIVE_WINDOW_GET_NEXT_FRAME_ID: res = dispatchGetNextFrameId(args); break; case NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS: res = dispatchEnableFrameTimestamps(args); break; Loading Loading @@ -960,6 +963,12 @@ int Surface::dispatchSetAutoRefresh(va_list args) { return setAutoRefresh(autoRefresh); } int Surface::dispatchGetNextFrameId(va_list args) { uint64_t* nextFrameId = va_arg(args, uint64_t*); *nextFrameId = getNextFrameNumber(); return NO_ERROR; } int Surface::dispatchEnableFrameTimestamps(va_list args) { bool enable = va_arg(args, int); enableFrameTimestamps(enable); Loading @@ -967,7 +976,7 @@ int Surface::dispatchEnableFrameTimestamps(va_list args) { } int Surface::dispatchGetFrameTimestamps(va_list args) { uint32_t framesAgo = va_arg(args, uint32_t); uint64_t frameId = va_arg(args, uint64_t); nsecs_t* outRequestedPresentTime = va_arg(args, int64_t*); nsecs_t* outAcquireTime = va_arg(args, int64_t*); nsecs_t* outLatchTime = va_arg(args, int64_t*); Loading @@ -978,7 +987,7 @@ int Surface::dispatchGetFrameTimestamps(va_list args) { 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, return getFrameTimestamps(frameId, outRequestedPresentTime, outAcquireTime, outLatchTime, outFirstRefreshStartTime, outLastRefreshStartTime, outGlCompositionDoneTime, outDisplayPresentTime, Loading
libs/gui/tests/Surface_test.cpp +45 −40 Original line number Diff line number Diff line Loading @@ -598,8 +598,8 @@ protected: mFrameTimestampsEnabled = true; } int getAllFrameTimestamps(uint32_t framesAgo) { return native_window_get_frame_timestamps(mWindow.get(), framesAgo, int getAllFrameTimestamps(uint64_t frameId) { return native_window_get_frame_timestamps(mWindow.get(), frameId, &outRequestedPresentTime, &outAcquireTime, &outLatchTime, &outFirstRefreshStartTime, &outLastRefreshStartTime, &outGpuCompositionDoneTime, &outDisplayPresentTime, Loading @@ -619,6 +619,13 @@ protected: outReleaseTime = -1; } uint64_t getNextFrameId() { uint64_t frameId = -1; int status = native_window_get_next_frame_id(mWindow.get(), &frameId); EXPECT_EQ(status, NO_ERROR); return frameId; } void dequeueAndQueue(uint64_t frameIndex) { int fence = -1; ANativeWindowBuffer* buffer = nullptr; Loading Loading @@ -748,6 +755,8 @@ TEST_F(GetFrameTimestampsTest, DefaultDisabled) { EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount); EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount); const uint64_t fId = getNextFrameId(); // Verify the producer doesn't get frame timestamps piggybacked on dequeue. ASSERT_EQ(NO_ERROR, mWindow->dequeueBuffer(mWindow.get(), &buffer, &fence)); EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount); Loading @@ -761,8 +770,7 @@ TEST_F(GetFrameTimestampsTest, DefaultDisabled) { EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount); // Verify attempts to get frame timestamps fail. const uint32_t framesAgo = 0; int result = getAllFrameTimestamps(framesAgo); int result = getAllFrameTimestamps(fId); EXPECT_EQ(INVALID_OPERATION, result); EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount); } Loading @@ -778,6 +786,8 @@ TEST_F(GetFrameTimestampsTest, EnabledSimple) { EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount); EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount); const uint64_t fId1 = getNextFrameId(); // Verify getFrameTimestamps is piggybacked on dequeue. ASSERT_EQ(NO_ERROR, mWindow->dequeueBuffer(mWindow.get(), &buffer, &fence)); EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount); Loading @@ -802,8 +812,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 = getAllFrameTimestamps(framesAgo); int result = getAllFrameTimestamps(fId1); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(3, mFakeConsumer->mGetFrameTimestampsCount); } Loading Loading @@ -833,16 +842,17 @@ TEST_F(GetFrameTimestampsTest, QueryRetireSupported) { QueryPresentRetireSupported(false, true); } // This test verifies that: // 1) The timestamps recorded in the consumer's FrameTimestampsHistory are // properly retrieved by the producer for the correct frames. // 2) When framesAgo is 0, it is querying for the most recently queued frame. // This verifies the timestamps recorded in the consumer's // FrameTimestampsHistory are properly retrieved by the producer for the // correct frames. TEST_F(GetFrameTimestampsTest, TimestampsAssociatedWithCorrectFrame) { enableFrameTimestamps(); const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); mFrames[0].signalQueueFences(); const uint64_t fId2 = getNextFrameId(); dequeueAndQueue(1); mFrames[1].signalQueueFences(); Loading @@ -853,9 +863,8 @@ TEST_F(GetFrameTimestampsTest, TimestampsAssociatedWithCorrectFrame) { mFrames[1].signalRefreshFences(); // Verify timestamps are correct for frame 1. uint32_t framesAgo = 1; resetTimestamps(); int result = getAllFrameTimestamps(framesAgo); int result = getAllFrameTimestamps(fId1); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime); Loading @@ -870,9 +879,8 @@ TEST_F(GetFrameTimestampsTest, TimestampsAssociatedWithCorrectFrame) { EXPECT_EQ(mFrames[0].kReleaseTime, outReleaseTime); // Verify timestamps are correct for frame 2. framesAgo = 0; resetTimestamps(); result = getAllFrameTimestamps(framesAgo); result = getAllFrameTimestamps(fId2); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime); EXPECT_EQ(mFrames[1].kProducerAcquireTime, outAcquireTime); Loading @@ -893,9 +901,8 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { enableFrameTimestamps(); mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true); const uint32_t framesAgo = 0; // Dequeue and queue frame 1. const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); // Verify queue-related timestamps for f1 are available immediately in the Loading @@ -903,7 +910,7 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { // acquire fence. resetTimestamps(); int oldCount = mFakeConsumer->mGetFrameTimestampsCount; int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, int result = native_window_get_frame_timestamps(mWindow.get(), fId1, &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); Loading @@ -915,7 +922,7 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { mFrames[0].signalQueueFences(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, result = native_window_get_frame_timestamps(mWindow.get(), fId1, &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); Loading @@ -924,6 +931,7 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime); // Dequeue and queue frame 2. const uint64_t fId2 = getNextFrameId(); dequeueAndQueue(1); // Verify queue-related timestamps for f2 are available immediately in the Loading @@ -931,7 +939,7 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { // acquire fence. resetTimestamps(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, result = native_window_get_frame_timestamps(mWindow.get(), fId2, &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); Loading @@ -943,7 +951,7 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { mFrames[1].signalQueueFences(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, result = native_window_get_frame_timestamps(mWindow.get(), fId2, &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); Loading @@ -961,6 +969,7 @@ TEST_F(GetFrameTimestampsTest, ZeroRequestedTimestampsNoSync) { mFrames[0].signalQueueFences(); // Dequeue and queue frame 2. const uint64_t fId2 = getNextFrameId(); dequeueAndQueue(1); mFrames[1].signalQueueFences(); Loading @@ -971,9 +980,8 @@ TEST_F(GetFrameTimestampsTest, ZeroRequestedTimestampsNoSync) { mFrames[1].signalRefreshFences(); // Verify a request for no timestamps doesn't result in a sync call. const uint32_t framesAgo = 0; int oldCount = mFakeConsumer->mGetFrameTimestampsCount; int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, int result = native_window_get_frame_timestamps(mWindow.get(), fId2, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(NO_ERROR, result); Loading @@ -987,6 +995,7 @@ TEST_F(GetFrameTimestampsTest, FencesInProducerNoSync) { mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true); // Dequeue and queue frame 1. const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); mFrames[0].signalQueueFences(); Loading @@ -1001,10 +1010,9 @@ TEST_F(GetFrameTimestampsTest, FencesInProducerNoSync) { // fence has been signaled. // Note: A sync call is necessary here since the events triggered by // addFrameEvents didn't get to piggyback on the earlier queues/dequeues. uint32_t framesAgo = 1; resetTimestamps(); int oldCount = mFakeConsumer->mGetFrameTimestampsCount; int result = getAllFrameTimestamps(framesAgo); int result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); Loading @@ -1021,10 +1029,9 @@ TEST_F(GetFrameTimestampsTest, FencesInProducerNoSync) { // Verify available timestamps are correct for frame 1 again, before any // fence has been signaled. // This time a sync call should not be necessary. framesAgo = 1; resetTimestamps(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; result = getAllFrameTimestamps(framesAgo); result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); Loading @@ -1043,10 +1050,9 @@ TEST_F(GetFrameTimestampsTest, FencesInProducerNoSync) { mFrames[0].signalReleaseFences(); // Verify all timestamps are available without a sync call. framesAgo = 1; resetTimestamps(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; result = getAllFrameTimestamps(framesAgo); result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); Loading @@ -1069,9 +1075,8 @@ TEST_F(GetFrameTimestampsTest, NoGpuNoSync) { enableFrameTimestamps(); mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true); const uint32_t framesAgo = 1; // Dequeue and queue frame 1. const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); mFrames[0].signalQueueFences(); Loading @@ -1088,7 +1093,7 @@ TEST_F(GetFrameTimestampsTest, NoGpuNoSync) { // addFrameEvents didn't get to piggyback on the earlier queues/dequeues. resetTimestamps(); int oldCount = mFakeConsumer->mGetFrameTimestampsCount; int result = getAllFrameTimestamps(framesAgo); int result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); Loading @@ -1110,7 +1115,7 @@ TEST_F(GetFrameTimestampsTest, NoGpuNoSync) { // sync call. resetTimestamps(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; result = getAllFrameTimestamps(framesAgo); result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); Loading @@ -1132,10 +1137,12 @@ TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) { mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true); // Dequeue and queue frame 1. const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); mFrames[0].signalQueueFences(); // Dequeue and queue frame 2. const uint64_t fId2 = getNextFrameId(); dequeueAndQueue(1); mFrames[1].signalQueueFences(); Loading @@ -1146,10 +1153,9 @@ TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) { // fence has been signaled. // Note: A sync call is necessary here since the events triggered by // addFrameEvents didn't get to piggyback on the earlier queues/dequeues. uint32_t framesAgo = 1; resetTimestamps(); int oldCount = mFakeConsumer->mGetFrameTimestampsCount; int result = getAllFrameTimestamps(framesAgo); int result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); Loading @@ -1167,15 +1173,14 @@ TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) { mFrames[0].signalReleaseFences(); mFrames[1].signalRefreshFences(); // Verify querying for all timestmaps of f2 does not do a sync call. // Even though the lastRefresh, retire, dequeueReady, and release times aren't // Verify querying for all timestmaps of f2 does not do a sync call. 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 = getAllFrameTimestamps(framesAgo); result = getAllFrameTimestamps(fId2); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime); Loading @@ -1200,14 +1205,14 @@ void GetFrameTimestampsTest::PresentOrRetireUnsupportedNoSyncTest( displayPresentSupported, displayRetireSupported); // Dequeue and queue frame 1. const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); // Verify a query for the Present and Retire times do not trigger // a sync call if they are not supported. const uint32_t framesAgo = 0; resetTimestamps(); int oldCount = mFakeConsumer->mGetFrameTimestampsCount; int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, int result = native_window_get_frame_timestamps(mWindow.get(), fId1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, displayPresentSupported ? nullptr : &outDisplayPresentTime, displayRetireSupported ? nullptr : &outDisplayRetireTime, Loading
opengl/include/EGL/eglext.h +4 −2 Original line number Diff line number Diff line Loading @@ -643,10 +643,12 @@ typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLCREATENATIVECLIENTBUFFERANDROID) (co #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 eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId); EGLAPI EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values); EGLAPI EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint timestamp); #else typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values); typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETNEXTFRAMEIDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId); typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSANDROID) (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values); typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYTIMESTAMPSUPPORTEDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint timestamp); #endif #endif Loading
opengl/libs/EGL/eglApi.cpp +39 −2 Original line number Diff line number Diff line Loading @@ -216,6 +216,8 @@ static const extention_map_t sExtensionMap[] = { (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR }, // EGL_ANDROID_get_frame_timestamps { "eglGetNextFrameIdANDROID", (__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID }, { "eglGetFrameTimestampsANDROID", (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID }, { "eglQueryTimestampSupportedANDROID", Loading Loading @@ -2048,8 +2050,42 @@ EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface, return EGL_FALSE; } EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId) { clearError(); const egl_display_ptr dp = validate_display(dpy); if (!dp) { return setError(EGL_BAD_DISPLAY, EGL_FALSE); } SurfaceRef _s(dp.get(), surface); if (!_s.get()) { return setError(EGL_BAD_SURFACE, EGL_FALSE); } egl_surface_t const * const s = get_surface(surface); if (!s->win.get()) { return setError(EGL_BAD_SURFACE, EGL_FALSE); } uint64_t nextFrameId = 0; status_t ret = native_window_get_next_frame_id(s->win.get(), &nextFrameId); if (ret != NO_ERROR) { // This should not happen. Return an error that is not in the spec // so it's obvious something is very wrong. ALOGE("eglGetNextFrameId: Unexpected error."); return setError(EGL_NOT_INITIALIZED, EGL_FALSE); } *frameId = nextFrameId; return EGL_TRUE; } EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values) { clearError(); Loading Loading @@ -2118,7 +2154,7 @@ EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, } } status_t ret = native_window_get_frame_timestamps(s->win.get(), framesAgo, status_t ret = native_window_get_frame_timestamps(s->win.get(), frameId, requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime, lastRefreshStartTime, GLCompositionDoneTime, displayPresentTime, displayRetireTime, dequeueReadyTime, releaseTime); Loading @@ -2135,6 +2171,7 @@ EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, default: // This should not happen. Return an error that is not in the spec // so it's obvious something is very wrong. ALOGE("eglGetFrameTimestamps: Unexpected error."); return setError(EGL_NOT_INITIALIZED, EGL_FALSE); } } Loading