How to limit framerate when using Android's GLSurfaceView.RENDERMODE_CONTINUOUSLY?

grinliz picture grinliz · Jan 23, 2011 · Viewed 30.6k times · Source

I have a C++ game running through JNI in Android. The frame rate varies from about 20-45fps due to scene complexity. Anything above 30fps is silly for the game; it's just burning battery. I'd like to limit the frame rate to 30 fps.

  • I could switch to RENDERMODE_WHEN_DIRTY, and use a Timer or ScheduledThreadPoolExecutor to requestRender(). But that adds a whole mess of extra moving parts that might or might not work consistently and correctly.
  • I tried injecting Thread.sleep() when things are running quickly, but this doesn't seem to work at all for small time values. And it may just be backing events into the queue anyway, not actually pausing.

Is there a "capFramerate()" method hiding in the API? Any reliable way to do this?

Answer

Fili picture Fili · Jun 10, 2011

The solution from Mark is almost good, but not entirely correct. The problem is that the swap itself takes a considerable amount of time (especially if the video driver is caching instructions). Therefore you have to take that into account or you'll end with a lower frame rate than desired. So the thing should be:

somewhere at the start (like the constructor):

startTime = System.currentTimeMillis();

then in the render loop:

public void onDrawFrame(GL10 gl)
{    
    endTime = System.currentTimeMillis();
    dt = endTime - startTime;
    if (dt < 33)
        Thread.Sleep(33 - dt);
    startTime = System.currentTimeMillis();

    UpdateGame(dt);
    RenderGame(gl);
}

This way you will take into account the time it takes to swap the buffers and the time to draw the frame.