I want to control the rendering rate of my GLSurfaceView.Renderer. I implemented a thread in the class that extends GLSurfaceView, and put it to sleep periodically in a while(true) loop, which did nothing to slow down the renderer. There's a good answer here that suggests putting the GL Thread to sleep by using a Thread.sleep within the Renderer.onDrawFrame() method. I'd like to handle it from outside the Renderer class. How can that be done when an explicit call requires passing in a GL10 object? Thanks.
Asked
Active
Viewed 3,995 times
2
-
As trivial as this sounds is it totally out of question to let onDrawFrame sleep once it gets called next time - meaning you could set a flag for it to happen? – harism May 04 '11 at 19:48
1 Answers
4
Don't extend GLSurfaceView. If you're not already, keep the renderer as a variable in your activity class:
public class MyActivity extends Activity {
protected GLSurfaceView mGLView;
protected GraphicsRenderer graphicsRenderer; // keep reference to renderer
protected void initGraphics() {
graphicsRenderer = new GraphicsRenderer(this);
mGLView = (GLSurfaceView) findViewById(R.id.graphics_glsurfaceview1);
mGLView.setEGLConfigChooser(true);
mGLView.setRenderer(graphicsRenderer);
graphicsRenderer.setFrameRate(30);
}
}
Then you can create a method in your renderer to control the frame rate:
public class GraphicsRenderer implements GLSurfaceView.Renderer {
private long framesPerSecond;
private long frameInterval; // the time it should take 1 frame to render
private final long millisecondsInSecond = 1000;
public void setFrameRate(long fps){
framesPerSecond = fps;
frameInterval= millisecondsInSeconds / framesPerSecond;
}
public void onDrawFrame(GL10 gl) {
// get the time at the start of the frame
long time = System.currentTimeMillis();
// drawing code goes here
// get the time taken to render the frame
long time2 = System.currentTimeMillis() - time;
// if time elapsed is less than the frame interval
if(time2 < frameInterval){
try {
// sleep the thread for the remaining time until the interval has elapsed
Thread.sleep(frameInterval - time2);
} catch (InterruptedException e) {
// Thread error
e.printStackTrace();
}
} else {
// framerate is slower than desired
}
}
}

James Coote
- 1,975
- 19
- 29
-
2Stalling onDrawFrame() may be problematic. Recent versions of Android synchronize onDrawFrame() with the "vsync" refresh on the device, so this can lead to choppy animation if the sleep() call is finishing right on the edge of the next frame. With onDrawFrame() being driven by an external clock, your ability to control the frame rate is essentially limited to rendering every N refreshes (e.g. draw every-other time onDrawFrame is called to cut the updates in half). sleep() may not be perfectly accurate. – fadden Feb 25 '13 at 21:22
-
Good point. I could swear there is a way to give a hint to the renderer for what frame rate you want, but I can't find any info on it now. For my own engine, I don't control frame rate, I just let it get on with it, but some people want to have more control – James Coote Feb 27 '13 at 14:54
-
1If your game state is updated relatively infrequently, you can put the renderer into `RENDERMODE_WHEN_DIRTY` and just `requestRender()` whenever there's something new to draw. – fadden Feb 27 '13 at 21:38
-
this idea is good, to implement more, you need to 1. set RENDERMODE_WHEN_DIRTY 2. move start-end thread and thread.sleep to other thread 3. call requestRender() to manual reload it – Sruit A.Suk Jul 05 '20 at 09:09