Android timing in OpenGL ES thread is not monotonic

橙三吉。 提交于 2019-12-18 05:25:34

问题


I'm measuring time interval for looped animations/particles/etc in my Android app. App is a live wallpaper so it doesn't prevent system from scaling clock down for power saving. Because of this all methods to measure time intervals between last frames doesn't measure monotonic time - I experience animations inconsistently slowing down and speeding up.

I've used all possible methods to retrieve system time - all of them are not monotonic (even SystemClock.elapsedRealtime() and System.nanoTime() which are guaranteed to be monotonic but nope they are not).

If I hold a finger on screen to prevent power saving all animations are smooth. This issue is very noticeable on Nexus10, slightly noticeable on Nexus7 1st gen and on Nexus4 it is not present at all.

Here is code excerpt to measure time:

public void onDrawFrame(GL10 glUnused) {
    // calculate timers for animations based on difference between lastFrameTime and SystemClock.elapsedRealtime()
    ...
    // save last timestamp for this frame
    lastFrameTime = SystemClock.elapsedRealtime();
}

回答1:


Expanding a little on what I think you're doing based on the outline of your code, your onDrawFrame() method in pseudo code looks like this:

deltaTime = SystemClock.elapsedRealtime() - lastFrameTrime
// point 1, see text below
update animation based on deltaTime
draw frame
// point 2, see text below
lastFrameTime = SystemClock.elapsedRealtime()

The problem with this sequence is that you lose the time between point 1 and point 2 from your total animation time. You need to make sure that the total sum of all your deltaTime values, which are the times applied to your animation, covers the entire wall clock time of the amimation. With the logic you use, this is not the case. You only add up the times between the end of one call to the start of the next call. You do not account for the time needed to execute the method, which can be significant.

This can be fixed with a slight change in the sequence:

currentTime = SystemClock.elapsedRealtime()
deltaTime = currentTime - lastFrameTime
lastFrameTime = currentTime
update animation based on deltaTime
draw frame

The key point is that you only call elapsedRealtime() once per frame.



来源:https://stackoverflow.com/questions/23411287/android-timing-in-opengl-es-thread-is-not-monotonic

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!