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

Commit 1049d1d0 authored by Brian Anderson's avatar Brian Anderson
Browse files

EGL: Use frameId instead of framesAgo for frame events.

Using a frameId allows an app to poll for timestamps
from a thread other than the swapping thread.

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

Change-Id: I3faac0513929837982a2e63f7e0d3d529bd28f10
parent 50e67545
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -206,6 +206,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);
+11 −2
Original line number Diff line number Diff line
@@ -833,6 +833,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;
@@ -962,6 +965,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);
@@ -969,7 +978,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*);
@@ -980,7 +989,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,
+45 −40
Original line number Diff line number Diff line
@@ -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,
@@ -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;
@@ -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);
@@ -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);
}
@@ -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);
@@ -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);
}
@@ -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();

@@ -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);
@@ -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);
@@ -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
@@ -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);
@@ -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);
@@ -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
@@ -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);
@@ -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);
@@ -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();

@@ -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);
@@ -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();

@@ -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);
@@ -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);
@@ -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);
@@ -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();

@@ -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);
@@ -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);
@@ -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();

@@ -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);
@@ -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);
@@ -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,
+4 −2
Original line number Diff line number Diff line
@@ -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
+39 −2
Original line number Diff line number Diff line
@@ -216,6 +216,8 @@ static const extention_map_t sExtensionMap[] = {
            (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },

    // EGL_ANDROID_get_frame_timestamps
    { "eglGetNextFrameIdANDROID",
            (__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID },
    { "eglGetFrameTimestampsANDROID",
            (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID },
    { "eglQueryTimestampSupportedANDROID",
@@ -2042,8 +2044,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();
@@ -2112,7 +2148,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);
@@ -2129,6 +2165,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